Search code examples
c#ninjectninject-interception

Ninject. Strange intercept to inner set-properties


Domain object:

TargetObject.cs

    public class TargetObject
    {
        public virtual ChildTargetObject ChildTargetObject
        {
            get { return ChildTargetObjectInner; }
            set { ChildTargetObjectInner = value; }
        }

        public virtual ChildTargetObject ChildTargetObjectInner { get; set; }
    }

Configuration and test:

        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();

In the last line we have change property ChildTargetObject and it change inner property ChildTargetObjectInner. But we didnt get interception of it. Why?

If I remove the "virtual" near ChildTargetObject it will be work fine (but this workaround impossible because I use NHiber).

If I change ChildTargetObjectInner directly (ex, o.ChildTargetObjectInner = new ChildTargetObject();), I got intercept.

How can I intercept of any changes (in class and out of class)? Thank you.


Solution

  • This is a limitation of the proxying framework and the way ninject creates a proxy.

    If you've got a virtual on the method, the method will be proxied/intercepted. however, when you remove the virtual, the method will not be proxied/intercepted anymore.

    Now apparently a proxied method making a call to another (proxied) method will not call the proxied method but rather the implementation. So you can't intercept these.

    You are probably using castle dynamic proxy. Krzysztof has written a very good tutorial about it, and it also covers virtual and non-virtual methods.

    Also note, that since you are using NHibernate, NHibernate will also create proxy. Now when you create a new entity, you may create it through ninject, which will proxy it and configure the interception. However, when you retrieve a persisted entity from the database, it will be created by NHibernate. It will also proxy it and put its interceptors on it. But it doesn't know about ninject's proxies and thus will not add these interceptors. Regarding this, you may want to look into


    Alternatively you could also decorate your methods using Fody MethodDecorator