Introduction
While implementing dependency injection, in MVC web applications and web APIs, sometimes we encounter a situation when we have to resolve an interface with two different instances of the same class implementing the interface. This is a challenge specifically in MVC web app and web API because, here we do not invoke the controller’s constructor ourselves.
In this situation, how to tell the unity container to first resolve an interface with one instance and then with another?
For example:
If we have an interface IAnimal
, and the controller constructor expects two different instances of the class Dog
which implements IAnimal
.
Interface IAnimal
{
string cry();
}
Public class Dog: IAnimal
{
string cry()
{
return “Woof!”;
}
}
class FamilyController: ApiController
{
IAnimal _parent;
IAnimal _child;
FamilyController (IAnimal parent, IAnimal child)
{
_parent= parent;
_child=child;
}
}
public static class Bootstrapper
{
public static IUnityContainer BuildUnityContainer()
{
var Container = new UnityContainer();
var papaDog=new Dog();
var babyDog= new Dog();
Container.RegisterInstance<IAnimal>(“parent”, papaDog);
Container.RegisterInstance<IAnimal>(“child”, babyDog);
}
}
When the controller is initialized by the framework, both the variable "parent
" as well as "child
" have reference to the instance babyDog
. This is because when the unity container is told to resolve the interface IAnimal
, it resolves it with the last registered instance that implements the interface.
The Solution
We can hint the unity container to initialize the type with certain resolutions whenever needed using InjectionFactory
. The code goes like this:
public static class Bootstrapper
{
public static IUnityContainer BuildUnityContainer()
{
var Container = new UnityContainer();
var papaDog=new Dog();
var babyDog= new Dog();
Container.RegisterInstance<IAnimal>(“parent”, papaDog);
Container.RegisterInstance<IAnimal>(“child”, babyDog);
Container.RegisterType(typeof(FamilyController), new InjectionFactory((c,t,s)=>
new FamilyController(
Container.Resolve<IAnimal>("parent"),
Container.Resolve<IAnimal>("child"))
);
}
}