Unity Container: Register and Resolve

In the previous section, we installed unity framework in our console project. Here, we will learn how to register type-mapping and resolve it using unity container.

As we learned in the IoC container chapter that every container must provide a way to register and resolve dependencies. Unity container provides RegisterType() and Resolve() methods for this.

We are going to use the following sample classes to demo registration and resolution of dependencies throughout this chapter.

public interface ICar
{
    int Run();
}

public class BMW : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }
}

public class Ford : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }
}

public class Audi : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }

}
public class Driver
{
    private ICar _car = null;

    public Driver(ICar car)
    {
        _car = car;
    }

    public void RunCar()
    {
        Console.WriteLine("Running {0} - {1} mile ", _car.GetType().Name, _car.Run());
    }
}

As you can see sample classes, Driver class depends on ICar interface. So, when we instantiate the Driver class object then we will have to pass an instance of a class which implement ICar interface such as BMW, Audi or Ford class as shown below.

Driver driver = new Driver(new BMW());

driver.RunCar();
Output:
Running BMW - 1 mile

In the above example, we created and passed an object of BMW while creating an object of Driver class. Thus, we injected dependency of Driver class manually. Now, use unity container and understand different ways to register and resolve dependencies.

Using UnityContainer.

In order to use unity container, we first need to create an object of it. You can use any class which implements IUnityContainer interface. Unity container includes UnityContainer class in Microsoft.Practices.Unity namespace that implements IUnityContainer interface. If you need to extend the container then you can create your own custom class and implement IUnityContainer interface as per your need.

Example: Instantiate UnityContainer
using Microsoft.Practices.Unity;

IUnityContainer container = new UnityContainer();
//or
var container = new UnityContainer();

Now, we need to register type-mapping next.

Register

Before unity resolve dependencies, we first need to register the type-mapping with the container, so that it can create the correct object for the given type. Use RegisterType() method to register a type mapping. Basically, it configures which class to instantiate, for which interface or base class. For example, if we want unity container to create and supply an object of BMW class whenever it needs to supply dependency of ICar interface, then you first need to register it as below.

Example: Register Type with Unity
IUnityContainer container = new UnityContainer();

container.RegisterType<ICar, BMW>();

The container.RegisterType<ICar, BMW>() asks unity that whenever you need to inject an object of ICar, then create an object of BMW class and inject it through a constructor by default.

The RegisterType method includes many overloads. Learn about all the overloads of RegisterType on MSDN.

So now, after registration, we can resolve it using Resolve() method.

Resolve

Unity creates an object of the specified class and automatically injects dependencies using resolve() method. We have registered BMW with ICar above. Now, we can instantiate the Driver class using unity container without using new keyword as shown below.

Example: Resolve
IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();// Map ICar with BMW 

//Resolves dependencies and returns Driver object 
Driver drv = container.Resolve<Driver>(); 
drv.RunCar();
Output:
Running BMW - 1 mile

In the above example, unity container creates an object of a class Driver using container.Resolve<driver>() method. The Driver class is a dependent on ICar. So, container.Resolve<Driver>() returns an object of Driver class by automatically creating and injecting BMW object in it. All this is behind the scene. It creates and injects BMW object because we register BMW type with ICar.

Unity container will create new object and inject it every time whenever we resolve the same type.

var container = new UnityContainer();
container.RegisterType<ICar, BMW>();

Driver driver1 = container.Resolve<Driver>();
driver1.RunCar();

Driver driver2 = container.Resolve<Driver>();
driver2.RunCar();
Output:
Running BMW - 1 mile
Running BMW - 1 mile

In the above example, container injects BMW object whenever it resolves Driver class e.g. driver1 and driver2 both has a reference of separate BMW objects.

Thus, you can create an object of the specified type using unity container. Learn about all the overloads of Resolve method on MSDN.

Multiple Registration

Unity container will inject last registered type if you register multiple mappings of the same type.

IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>();

Driver driver = container.Resolve<Driver>();
driver.RunCar();
Output:
Running Audi - 1 Mile

In the above example, ICar is mapped to both BMW and Audi. But, unity will inject Audi every time because it has been registered last.

Register Named Type

You can register a type-mapping with a name which you can use with Resolve method.

Example: Register Named Type
IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>("LuxuryCar");

ICar bmw = container.Resolve<ICar>();  // return BMW object
ICar audi = container.Resolve<ICar>("LuxuryCar"); // return Audi object

As you can see above, we have mapped ICar with both BMW and Audi class. However, we have given a name "LuxuryCar" to ICar-Audi mapping. So now, Resolve() method will return an object of Audi if we specify the mapping name.

Now, consider the following example.

var container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>("LuxuryCar");

// Register Driver type            
container.RegisterType<Driver>("LuxuryCarDriver", 
                new InjectionConstructor(container.Resolve<ICar>("LuxuryCar")));

Driver driver1 = container.Resolve<Driver>();// injects BMW
driver1.RunCar();

Driver driver2 = container.Resolve<Driver>("LuxuryCarDriver");// injects Audi
driver2.RunCar();
Output:
Running BMW - 1 Mile
Running Audi - 1 Mile

In the above example, we registered Driver class with the name "LuxuryCarDriver" and specified an object of InjectionConstructor. The new InjectionConstructor(container.Resolve<ICar>("LuxuryCar")) specifies a construction injection for Driver class which passes an object of Audi because container.Resolve("LuxuryCar") returns Audi object. So now, we can use container.Resolve<Driver>("LuxuryCarDriver") to resolve Driver with Audi even if ICar is registered with BMW by default.

Register Instance

Unity container allows us to register an existing instance using RegisterInstance() method. So, unity container will not create a new instance for the registered type and will use the same instance every time.

var container = new UnityContainer();
ICar audi = new Audi();
container.RegisterInstance<ICar>(audi);

Driver driver1 = container.Resolve<Driver>();
driver1.RunCar();
driver1.RunCar();

Driver driver2 = container.Resolve<Driver>();
driver2.RunCar();
Output:
Running Audi - 1 Mile
Running Audi - 2 Mile
Running Audi - 3 Mile

Thus, we can register and resolve different types using Unity container. Learn how Unity container performs constructor injection in the next chapter.