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的代理,因此不会添加这些拦截器。 关于这一点,你可能想要研究一下


或者,您也可以使用Fody MethodDecorator来装饰您的方法