Ninject。 对内部集合属性的奇怪拦截
域对象:
TargetObject.cs
public class TargetObject { public virtual ChildTargetObject ChildTargetObject { get { return ChildTargetObjectInner; } set { ChildTargetObjectInner = value; } } public virtual ChildTargetObject ChildTargetObjectInner { get; set; } }
配置和测试:
var settings = new NinjectSettings { InjectNonPublic = true, AllowNullInjection = true }; var kernel = new StandardKernel(settings); kernel.Bind().ToSelf(); kernel.InterceptReplaceSet(t => t.ChildTargetObjectInner, (inv) => { inv.Proceed(); // <= we never step here. Why? } ); var o = kernel.Get(); o.ChildTargetObject = new ChildTargetObject();
在最后一行中,我们更改了属性ChildTargetObject ,它更改了内部属性ChildTargetObjectInner 。 但是我们没有拦截它。 为什么?
如果我删除ChildTargetObject附近的“虚拟”它将工作正常(但这种解决方法不可能因为我使用NHiber)。
如果我直接更改ChildTargetObjectInner ( 例如,o.ChildTargetObjectInner = new ChildTargetObject(); ),我得到了拦截。
我怎样才能拦截任何变化(课堂上和课外)? 谢谢。
这是代理框架的限制以及ninject创建代理的方式。
如果你有一个virtual
的方法,该方法将被代理/拦截。 但是,当您删除virtual
,该方法将不再被代理/拦截。
现在显然,调用另一个(代理)方法的代理方法不会调用代理方法而是调用实现。 所以你不能拦截这些。
您可能正在使用城堡动态代理。 Krzysztof写了一篇关于它的非常好的教程 ,它还包括虚拟和非虚拟方法。
另请注意,由于您使用的是NHibernate,因此NHibernate也会创建代理。 现在,当您创建一个新实体时,您可以通过ninject创建它,它将代理它并配置拦截。 但是,当您从数据库中检索持久化实体时,它将由NHibernate创建。 它也会代理它并将拦截器放在它上面。 但它不知道ninject的代理,因此不会添加这些拦截器。 关于这一点,你可能想要研究一下
- http://nhibernate.info/blog/2008/12/12/entities-behavior-injection.html
- http://blog.scooletz.com/2011/02/14/nhibernate-interceptor-magic-tricks-pt-3/
或者,您也可以使用Fody MethodDecorator来装饰您的方法