0

I am working on an ASP.NET Web API which contains multiple Web API Controllers. Each controller has a dependency on IMessageSender.

public class OrderController: ApiController {
    private readonly IMessageSender _msgSender;
    public OrderController(IMessageSender msgSender) {
        _msgSender = msSender;
    }
}

I have 3 different different implementations of IMessageSender - CloudMessageSender, InMemoryMessageSender and NServiceBusMessageSender.

public class CloudMessageSender: IMessageSender 
{
}
public class InMemoryMessageSender: IMessageSender 
{
}
public class NServiceBusMessageSender: IMessageSender 
{
}

I am using Unity and Unity.WebApi for dependency resolution and have registered 3 named registrations of IMessageSender

container.RegisterType<IMessageSender, CloudMessageSender>("res-cloud");
container.RegisterType<IMessageSender, InMemoryMessageSender>("res-inmem");
container.RegisterType<IMessageSender, NServiceBusMessageSender>("res-nsvc");

The problem that I am facing is that for different controllers I need to use a different Implementation of IMessageSender. Ex. OrdersController need to use the CloudMessageSender but CustomersController need to use the InMemoryMessageSender. By default Unity will inject either the un-named resolution or (in my case) the first one.

How can I specify or control as to which controller should be injected with which implementation of IMessageSender?

Pratik Bhattacharya
  • 3,596
  • 2
  • 32
  • 60
  • http://stackoverflow.com/questions/18665324/unity-register-for-one-interface-multiple-object-and-tell-unity-where-to-inject – Chetan Feb 16 '17 at 10:08
  • When you start having named registrations, it is better to switch to [Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di/). See this article for more details: http://criticalsoftwareblog.com/index.php/2015/08/23/why-di-containers-fail-with-complex-object-graphs/ – Yacoub Massad Feb 16 '17 at 10:15

1 Answers1

1

You can configured the container to register for Controller type too with injection members. In the list of injection members you can resolve the already registered dependencies by the name. This way it will be made sure that the proper type gets resolved when the controller instance is created.

container.RegisterType<IMessageSender, CloudMessageSender>("res-cloud");
container.RegisterType<IMessageSender, InMemoryMessageSender>("res-inmem");
container.RegisterType<IMessageSender, NServiceBusMessageSender>("res-nsvc");

var messageSender = new ResolvedParameter<IMessageService>("res-cloud");
container.RegisterType<OrderController>(new InjectionConstructor(messageSender));

Now when OrderController instance is initialized, type of msgSender argument will be resolved to CloudMessageSender.

One issue with this way of registering controller is that you need to resolve and pass all the parameters of constructor of the controller.

Unity does not support resolving types based on name without using this approach.

Chetan
  • 6,711
  • 3
  • 22
  • 32
  • "Unity does not support resolving types based on name without using this approach." - which is a good reason not to use Unity. The fact that it hasn't had an update in several years is another. – NightOwl888 Feb 16 '17 at 12:26
  • Well whether to use it or not depends on case by case. Using unit with MVC simplifies setup and configuration as compared to others such as Castle Windsor . Agree, that Unity should have upgraded themselves to be in line with IoC containers. – Chetan Feb 16 '17 at 12:37