Search code examples
c#unity-container

Unity: Registering the same type for two interfaces


I'm seeing a weird behaviour in the Unity container, when working with two interfaces, that both register to the same decorator. A code example will be clearer.

I have the following class hierarchy:

   public interface IBaseInterface
    {

    }

    public interface IInterface1: IBaseInterface
    {

    }
    public interface IInterface2: IBaseInterface
    {

    }
    public class Interface1Impl : IInterface1
    {
    }
    public class Interface2Impl : IInterface2
    {
    }

    public class BaseInterfaceDecorator: IInterface1,IInterface2
    {
        private readonly IBaseInterface baseInterface;

        public BaseInterfaceDecorator(IBaseInterface baseInterface)
        {
            this.baseInterface = baseInterface;
        }
    }

    public class MyClass
    {
        private readonly IInterface1 interface1;

        public MyClass(IInterface1 interface1)
        {
            this.interface1 = interface1;
        }            
    }

And this is the registration code:

var container = new UnityContainer();           
        container.RegisterType<IInterface1, BaseInterfaceDecorator>(
            new InjectionConstructor(
                new ResolvedParameter<Interface1Impl>()));

        container.RegisterType<IInterface2, BaseInterfaceDecorator>(
           new InjectionConstructor(
               new ResolvedParameter<Interface2Impl>()));


        var dependency = container.Resolve<MyClass>();

When resolving MyClass I'm getting a BaseInterfaceDecorator with Interface2Impl instead of Interface1Impl. Seems strange to me. Can you explain?


Solution

  • It looks like the last injection instruction for a given "to" type wins. If you grab a copy of Reflector and take a look at the UnityContainer.RegisterType(Type, Type, string, LifetimeManager, InjectionMember[]) implementation, you'll see why.

    IMO, this behaviour is a bug. At the very least, InjectedMembers.ConfigureInjectionFor(Type, string, InjectionMember[]) should throw an exception instead of silently replacing the previous injection configuration. However, it really ought to support what you are attempting.