域对象:
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<TargetObject>().ToSelf();
kernel.InterceptReplaceSet<TargetObject>(t => t.ChildTargetObjectInner,
(inv) =>
{
inv.Proceed(); // <= we never step here. Why?
}
);
var o = kernel.Get<TargetObject>();
o.ChildTargetObject = new ChildTargetObject();
在最后一行我们有改变属性ChildTargetObject,它改变内部属性ChildTargetObjectInner。但是我们没有拦截它。为什么?
如果我删除ChildTargetObject附近的"虚拟",它将工作得很好(但这个解决方案不可能,因为我使用NHiber)。
如果我直接改变ChildTargetObjectInner (ex, o.ChildTargetObjectInner = new ChildTargetObject();),我得到了拦截。
我如何拦截任何更改(类内和类外)?谢谢你!
这是代理框架和ninject创建代理的方式的限制。
如果方法上有virtual
,则该方法将被代理/拦截。但是,当您删除virtual
时,该方法将不再被代理/拦截。
现在很明显,一个被代理的方法调用另一个(被代理的)方法将不会调用被代理的方法,而是调用实现。所以你不能截取这些
您可能正在使用castle动态代理。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