我刚刚将一个相对较大的代码库从 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 转换MethodInfo
为invocation.Request.Target.GetType()
(返回实现类型 - Foo
)MethodInfo
。
有什么建议吗?