0

我刚刚将一个相对较大的代码库从 Ninject 2.2 升级到了 Ninject 3.0。一切似乎都按计划进行,除了我必须对我们使用的拦截内容进行一些更改。

interface IFoo
{
    Bar GetBar();
}

class Foo : IFoo
{
    [LogMethod(Level = LogLevel.Error)]
    public virtual Bar GetBar()
    {
        return new Bar();
    }
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
class LogMethodAttribute : InterceptAttribute
{
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return request.Kernel.Get<ILogMethodInterceptor>();
    }

    public LogLevel Level { get; set; }
}

interface ILogMethodInterceptor : IInterceptor { }

class LogMethodInterceptor : ILogMethodInterceptor 
{
    public void Intercept(IInvocation invocation)
    {
        LogMethodAttribute attr = (LogMethodAttribute)invocation.Request.Method.GetCustomAttributes(typeof(LogMethodAttribute), true).FirstOrDefault();

        // Log something - using attribute properties
    }
}

NinjectSettings settings = new NinjectSettings { LoadExtensions = false };
IKernel kernel = new StandardKernel(settings, new DynamicProxy2Module());
kernel.Bind<ILogMethodInterceptor>().To<LogMethodInterceptor>();
kernel.Bind<IFoo>().To<Foo>();

这个精简版是我们过去在 Ninject 2.3 中发挥出色效果的版本。因为不允许使用接口代理,所以我们将所有方法都标记为虚拟,这使得 Castle 动态代理能够覆盖它们。

现在我想将 [LogMethod] 移动到接口级别以使用接口代理:

但是,当我移动它时,Ninject 不再检测到我要拦截这个类。此外,如果我保持原样,则会出现一个更微妙的问题:

invocation.Request.Method是来自接口的 MethodInfo IFoo- 不是实现Foo,这意味着我无法再检索我的属性。所以我暂时陷入了这两个问题之间——如果我把属性放在接口中,Ninject 不会创建代理,如果我把属性放在实现中,我不能轻易地检索我的属性来访问它的属性。目前我唯一的解决方案是:

interface IFoo
{
    [LogMethod(Level = LogLevel.Error)]
    Bar GetBar();
}

class Foo : IFoo
{
    [LogMethod(Level = LogLevel.Error)]
    public virtual Bar GetBar()
    {
        return new Bar();
    }
}

或者使用 InterfaceMapping 将我的 IFoo 转换MethodInfoinvocation.Request.Target.GetType()(返回实现类型 - FooMethodInfo

有什么建议吗?

4

0 回答 0