Object composition, aka mixins, aka introductions

Jun 22, 2009 at 1:37 PM

Regarding the topic, I’ve tried to implement a common example – automatic INotifyPropertyChanged implementation. I’ve hit a couple of problems, first and foremost http://unity.codeplex.com/WorkItem/View.aspx?WorkItemId=4608 . After that I moved to a more synthetic example. Let’s say I have the following interfaces:

    public interface I1

    {

        void M1();

        void M3();

    }

 

    public interface I2

    {

        void M2();

        void M4();

    }

 

I have implementations for them that look like this:

    public class I1Impl : I1

    {

        private readonly I1 outer;

 

        public I1Impl(I1 outer)

        {

            if (outer == null)

            {

                throw new ArgumentNullException("outer");

            }

            this.outer = outer;

        }

 

        public void M1()

        {

            Debug.WriteLine("I1.M1 implementation on behalf of {0}", outer);

        }

 

        public void M3()

        {

            Debug.WriteLine("I1.M3 implementation on behalf of {0}", outer);

        }

    }

I’m passing the “outer” object in case the implementation will have to deal with object identity.

And finally, I have a class that should implement I1 and I2:

    public class C

    {

    }

 

The following issues arise:

1.       First of all, Unity can’t generate neither instance nor type interceptors exposing multiple interfaces. So I’m left with virtual method interceptor and “stub” implementations:

    public class C : I1, I2

    {

        #region I1 Members

 

        public virtual void M1()

        {

            throw new NotImplementedException();

        }

 

        public virtual void M3()

        {

            throw new NotImplementedException();

        }

 

        #endregion

 

        #region I2 Members

 

        public virtual void M2()

        {

            throw new NotImplementedException();

        }

 

        public virtual void M4()

        {

            throw new NotImplementedException();

        }

 

        #endregion

    }

2.       Then, I find out that there is no good place to store the implementation objects – if I configure Unity like this:

            unity

                .Configure<Interception>()

                .AddPolicy(Guid.NewGuid().ToString())

                .AddMatchingRule(new TypeMatchingRule(typeof(C)))

                .AddCallHandler<I1I2Handler>();

…I find out that an instance of my call handler (in which I'd like to store the implementations for a single target object) is created for each method per type, so currently it works kinda orthogonally to what I want (an instance of handler per instance of target object)

3.       Finally, in the handler proper, the only way to call the method on the implementation type is by reflection, and I have to look in two interface maps (in C’s map to find Ix.Mx, and in IxImpl’s map to find IxImpl.Mx). It’s ugly and possibly slow.

My question is, is there any way to achieve what I want other than the way described above? With Castle DynamicProxy2 1. just works, 2. does not apply since DP operates at a lower level and you have to provide the interceptor instance yourself, and in regard to 3., I am provided either with a delegate instance I can just invoke on the implementation object, when I use this method:

http://api.castleproject.org/html/M_Castle_DynamicProxy_ProxyGenerator_CreateInterfaceProxyTypeWithTarget.htm

..or I can replace the target of the invocation with the implementation object entirely (so that interceptors down the chain can process it further – equivalent to having the Target property on IMethodInvocation writable), with this method:

http://api.castleproject.org/html/M_Castle_DynamicProxy_ProxyGenerator_CreateInterfaceProxyTypeWithTargetInterface.htm

DP2 also has its own “simplified” mixin mechanism, though it apparently does not support aggregation (aka access to “outer”).

I am thinking of replacing the Unity interception extension with a custom one utilizing DP2, but it’s obviously a lot of work. Castle Windsor has DP2 integration but it either has no way to configure mixins/interceptors at the level of detail I need or it’s not documented. Which brings me to the second question: is anything like this planned for Unity? I like the core container functionality, but the interception mechanism is lacking in the ways described above. I’m targeting .NET 4.0, and with no Postsharp for it the only way to achieve what I want is by low-level utilization of Castle DP2, which is an unwanted dependency that does not integrate with Unity. I’m starting to miss COM/ATL.

Oct 28, 2009 at 6:49 PM

This scenario is now implemented in Unity 2.0.