我刚刚将一个相对较大的代码库从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
是接口IFoo
中的MethodInfo - 而不是实现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
。
有什么建议吗?