With Unity how do I inject a named dependency into a constructor?

Vaccano picture Vaccano · Aug 12, 2011 · Viewed 36.9k times · Source

I have the IRespository registered twice (with names) in the following code:

// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
    ("Client", new InjectionConstructor(typeof(ClientEntities)));

// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
    ("Customer", new InjectionConstructor(typeof(CustomerEntities)));

IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();

But then when I want to resolve this (to use the IRepository) I have to do a manual resolve like this:

public ClientModel(IUnityContainer container)
{
   this.dataAccess = container.Resolve<IRepository>(Client);

   .....
}

What I would like to do is to have it resolved in the constructor (just like IUnityContainer). I need some way to say which named type to resolve to.

Something like this: (NOTE: Not real code)

public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
   this.dataAccess = dataAccess;

   .....
}

Is there a way to make my fake code work?

Answer

Chris Tavares picture Chris Tavares · Aug 13, 2011

You can configure dependencies with or without names in the API, attributes, or via the config file. You didn't mention XML above, so I'll assume you're using the API.

To tell the container to resolve a named dependency, you'll need to use an InjectionParameter object. For your ClientModel example, do this:

container.RegisterType<IClientModel, ClientModel>(
    new InjectionConstructor(                        // Explicitly specify a constructor
        new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client"
    )
);

This tells the container "When resolving ClientModel, call the constructor that takes a single IRepository parameter. When resolving that parameter, resolve with the name 'Client' in addition to the type."

If you wanted to use attributes, your example almost works, you just need to change the attribute name:

public ClientModel([Dependency("Client")] IRepository dataAccess)
{
   this.dataAccess = dataAccess;

   .....
}