Unity Container: Overrides
We have seen in the previous chapters that the Unity container injects the 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 a registered type by using ResolverOverride
. The ResolverOverride
is an abstract class that provides implementation for overriding registration. There are three important classes which inherit ResolverOverride
:
- ParameterOverride: Used to override constructor parameters.
- PropertyOverride: Used to override the value of a specified property.
- 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 a constructor parameter.
var container = new UnityContainer()
.RegisterType<ICar, BMW>();
var driver1 = container.Resolve<Driver>(); // Injects registered ICar type
driver1.RunCar();
// Overrides the registered ICar type
var driver2 = container.Resolve<Driver>(new ParameterOverride("car", new Ford()));
driver2.RunCar();
Running Ford - 1 Mile
In the above example, Unity container injects BMW in driver1
which is default mapping. However, we override the default mapping and specify a different mapping for driver2
by passing new ParameterOverride("car", new Ford())
into the Resolve()
method. The first parameter is the name of the constructor parameter and the second is the value of the parameter. So, driver2
includes an object of the Ford
class instead of the BMW
class.
If a constructor includes multiple parameters, then we can override them by passing an array of ResolverOverride
as shown below.
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 a registered property injection and provide a different property value when you resolve it.
var container = new UnityContainer();
//Configure the default value of the Car property
container.RegisterType<Driver>(new InjectionProperty("Car", new BMW()));
var driver1 = container.Resolve<Driver>();
driver1.RunCar();
//Override the default value of the Car property
var driver2 = container.Resolve<Driver>(
new PropertyOverride("Car", new Audi()
);
driver2.RunCar();
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 a constructor, a property or a method.
You can override a registered method injection and provide a different parameter value when you resolve it. Consider the following example.
var container = new UnityContainer()
.RegisterType<ICar, BMW>();
var driver1 = container.Resolve<Driver>();
driver1.RunCar();
//Override the dependency
var driver2 = container.Resolve<Driver>(new DependencyOverride<ICar>(new Audi())
driver2.RunCar();
Running Audi - 1 mile
Learn more about resolving Objects by Using Overrides.