Unity Container: Overrides

We have seen in the previous chapters that the unity container injects registered type by default every time we resolve the specified type. But, what if we want to inject different types other than the registered type?

Unity container allows us to override registered type by using ResolverOverride. ResolverOverride is an abstract class that provides implementation for overriding registration. There are three important classes which inherit ResolverOverride:

  1. ParameterOverride: Used to override constructor parameters.
  2. PropertyOverride: Used to override the value of specified property.
  3. DependencyOverride: Used to override the type of dependency and its value.

Let's understand each override using the following example classes.

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());
    }
}

ParameterOverride

The ParameterOverride can be used to override registered construction parameter values.

The following example demonstrates overriding constructor parameter.

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

var driver1 = container.Resolve<Driver>(); // Injects registered ICar type
driver1.RunCar();

// Override registered ICar type 
var driver2 = container.Resolve<Driver>(new ParameterOverride("car", new Ford()));
driver2.RunCar();
Output:
Running BMW - 1 Mile
Running Ford - 1 Mile

In the above example, unity container injects BMW in driver1 which is default mapping. However, we override default mapping and specify a different mapping for driver2 by passing new ParameterOverride("car", new Ford()) into Resolve() method. The first parameter is the name of the constructor parameter and second is the value of a parameter. So, driver2 includes an object of Ford class instead of BMW class.

If a constructor includes multiple parameters then we can override them by passing an array of ResolverOverride as shown below.

Example: Override Multiple Parameters
var container = new UnityContainer()
                .RegisterType<ICar, BMW>();

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

var driver2 = container.Resolve<Driver>( new ResolverOverride[] { 
        new ParameterOverride("car1", new Ford()),
        new ParameterOverride("car2", new BMW()),
        new ParameterOverride("car3", new Audi())
});
driver2.RunCar();

PropertyOverride

We learned about Property Injection in the previous chapter. Here, we will learn how to override the registered value of the specified property using PropertyOverride.

You can override registered property injection and provide different property value when you resolve it.

Example: PropertyOverride
var container = new UnityContainer();
            
//Configure default value of Car property
container.RegisterType<Driver>(new InjectionProperty("Car", new BMW()));

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

//Override default value of Car property
var driver2 = container.Resolve<Driver>(
    new PropertyOverride("Car", new Audi()
);

driver2.RunCar();
Output:
BMW - 1 mile
Audi - 1 mile

DependencyOverride

The DependencyOverride class can be used to override the type of dependency and its value, irrespective of whether dependencies are provided through constructor, property or a method.

You can override registered method injection and provide different parameter value when you resolve it. Consider the following example.

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

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

//Override dependency
var driver2 = container.Resolve<Driver>(new DependencyOverride<ICar>(new Audi())
driver2.RunCar();
Output:
Running BMW - 1 mile
Running Audi - 1 mile

Learn more about resolving Objects by Using Overrides.