Resolving Objects by Using Overrides
The parameter and dependency overrides, ParameterOverride and DependencyOverride, are ResolverOverride implementations that provide support for overriding the registration information for resolving instances of types. When you call the Resolve method, these classes enable you to override values specified when the type was registered, such as by a RegisterType or RegisterInstance statement. In effect, RegisterType supplied values are overridden by Resolve supplied values.
Use ParameterOverride to override the specified constructor parameter or parameters. The override applies everywhere the parameter appears unless you use OnType to constrain the override to a specified type. Since the purpose of overrides is to affect the resolution of dependencies for all relevant created objects, not just the object requested in the call to Resolve, unconstrained overrides can produce errors if there are unconstrained ParameterOverride parameters that match parameters with the same name but different types on the selected constructors for objects created in a given resolve operation.
Use PropertyOverride to override the value of the specified property or properties. The override applies everywhere the property appears unless you use OnType to constrain the override to a specified type.
Use DependencyOverride to override the value injected whenever there is a dependency of the given type. DependencyOverride overrides all instances where the type matches. Both parameter overrides and dependency overrides support generic types and multiple overrides.
Note
If the overridden object was previously created and is a Singleton, the override is ignored. The lifetime manager takes precedence and Singletons always return the same instance.
The container does not store a reference for the overridden object.
Overrides work with the constructor that is selected for the type, by attribute or configuration. If the constructor to be used is not identified with an attribute or explicit container configuration, then the default behavior is that the constructor with the most parameters will be used.
A parameter and property override never affects what element gets selected. They only control the value of the specified parameter or property. You do not change which constructor is called with an override, and you do not change which properties get set with an override.
Note
If the property is not set as a dependency through attribute, container API, or configuration file, then the override does nothing.
This topic contains the following sections to explain overrides in more detail:
- Using Parameter Overrides
- Using Property Overrides
- Using Dependency Overrides
- More Information
Using Parameter Overrides
ParameterOverride enables you to pass in values for constructor parameters to override a parameter passed to a given named constructor. Only the parameter value is overridden, not the constructor.
Note
ParameterOverride can be used only for constructors.
The following code constrains the override to the NewCar instance.
var anInstance = container.Resolve<ClassCar>(new ParameterOverride("car", "new car").OnType<NewCar>());
'Usage
Dim anInstance = container.Resolve(Of ClassCar)(New ParameterOverride("car", "new car").OnType(Of NewCar)())
Note
If the parameter does not exist, then the override is ignored.
When the parameters you set to override do not match the constructor signature, then the default parameter values set during registration are used.
You can override the constructor parameters but not the constructor.
The two parameters for ParameterOverride (parameterName, and parameterValue), specify the name of the parameter to override and the value to use for the parameter, respectively. In the following example the value ExpectedValue overrides the constructor's value for the constructor's parameter x for the type MyObject. The OnType method enables you to optionally specify a type to constrain the override to.
// Arbitrary values
const int ConfiguredValue = 15;
const int ExpectedValue = 42;
// Create a container and register type "MyObject"
var container = new UnityContainer()
.RegisterType<MyObject>(new InjectionConstructor(ConfiguredValue));
// Override the constructor parameter "x" value
// Use "ExpectedValue" instead of "ConfiguredValue"
var result = container.Resolve<MyObject>(
new ParameterOverride("x", ExpectedValue)
.OnType<MyOtherObject>());
'Usage
' Arbitrary values
Const ConfiguredValue As Integer = 15
Const ExpectedValue As Integer = 42
' Create a container and register type "MyObject"
Dim container = New UnityContainer().RegisterType(Of MyObject)(New InjectionConstructor(ConfiguredValue))
' Override the constructor parameter "x" value
' Use "ExpectedValue" instead of "ConfiguredValue"
Dim result = container.Resolve(Of MyObject)( _
New ParameterOverride("x", ExpectedValue) _
.OnType(Of MyOtherObject)())
Unity also supports overriding multiple parameters and the use of generics.
ParameterOverrides is a convenience form of ParameterOverride that lets you specify multiple parameter overrides in one statement rather than having to construct multiple objects, one for each override. The following example overrides the two parameters, y and x, with ExpectedValue.
const int ExpectedValue = 42;
var container = new UnityContainer();
var result = container.Resolve<MyObject>(
new ParameterOverrides
{
{ "y", ExpectedValue * 2 },
{ "x", ExpectedValue }
}
.OnType<MyOtherObject>());
For Visual Basic .NET you must either use discrete ParameterOverride objects instead of the grouped one, or do something like the following:
'Usage
Const ExpectedValue As Integer = 42
Dim container = New UnityContainer()
Dim overrides as new ParameterOverrides
With overrides
.Add("y", ExpectedValue * 2)
.Add("x", ExpectedValue)
End With
Dim result = container.Resolve(Of MyObject)(overrides.OnType(Of MyOtherObject)())
This could be useful in cases where your object contains both entities and services. You might wish to change an entity, but the service is fine as is. For example, you could process a series of customers and their information from your database and want to log the process. You have the following class where IErrorLogger logger and IDataAccess db are services.
class Customer
{
public customer(System.Int32 id, System.String name, IErrorLogger logger, IDataAccess db)
{
}
}
'Usage
Class Customer
Private Function customer(ByVal id As System.Int32, ByVal name As System.String, _
ByVal logger As IErrorLogger, ByVal db As IDataAccess)
End Function
End Class
If you register the type and specify the id and name for a customer, say Sam, then container.Resolve<Customer> will resolve with Sam every time. What you really want as you process customers in your database is to resolve a different customer every time you use container.Resolve<Customer>.
Using the plural form, ParameterOverrides, you can override just the relevant parameters for the constructor. Your object will have the services and you will have a new customer to work with.
container.Resolve<Customer>(
new ParameterOverrides
{
{"id", userform.id},
{ "name", "Bob"}
}.OnType<Customer>()
);
Visual Basic .NET lacks the dictionary initialization syntax to accomplish the same thing. You must either use discrete ParameterOverride objects instead of the grouped one, or do something like the following:
'Usage
Dim overrides as new ParameterOverrides
With overrides
.Add("id", userform.id)
.Add("name", "Bob")
End With
Dim result = container.Resolve(Of customer)(overrides.OnType(Of Customer)))
Using Property Overrides
PropertyOverride enables you to override the value for a specified property. Only the property value is overridden, not the properties selected. Its behavior is the same as ParameterOverride. The use of the OnType method enables you to specify a type to constrain the override to.
The following code specifies a value, overrideValue, to use to override the injected property value, defaultObject.
container.RegisterType<TargetTypeForInjection>(
new InjectionProperty("InjectedObject", defaultObject));
var result1 = container.Resolve<TargetTypeForInjection>(
new PropertyOverride("InjectedObject", overrideValue));
'Usage
container.RegisterType(Of TargetTypeForInjection)( _
New InjectionProperty("InjectedObject", defaultObject))
Dim result1 = container.Resolve(Of TargetTypeForInjection)( _
New PropertyOverride("InjectedObject", overrideValue))
The following code constrains the override to the TargetType2 instance by invoking OnType.
var result = container.Resolve<TargetTypeForInjection>(
new PropertyOverride("InjectedObject", overrideObject)
.OnType<TargetType2>());
'Usage
Dim result = container.Resolve(Of TargetTypeForInjection)( _
New PropertyOverride("InjectedObject", overrideObject) _
.OnType(Of TargetType2)())
Note
If the property is not set as a dependency through an attribute, the container API, or by a configuration file, then the override has no effect.
PropertyOverrides is a convenience form of PropertyOverride that lets you specify multiple property overrides in one statement rather than having to construct multiple objects, one for each override. Its behavior is the same as ParameterOverrides. The following example overrides the values for three properties of MyObject and constrains the overrides to MyOtherObject by using OnType.
return container.Resolve<MyObject>(
new PropertyOverrides
{
{"Property1", Value1},
{"Property2", Value2},
{"Property3", Value3}
}
.OnType<MyOtherObject>()
);
For Visual Basic .NET you must either use discrete PropertyOverride objects instead of the grouped one, or do something like the following:
'Usage
Dim overrides as new PropertyOverrides
With overrides
.Add("Property1", Value1)
.Add("Property2", Value2)
.Add("Property3", Value3)
End With
Dim result = container.Resolve(Of MyObject)(overrides.OnType(Of MyOtherObject)())
Using Dependency Overrides
DependencyOverride enables you to specify an override of the registered value injected for the specified dependency type, and enables you to pass in a different object that will be provided by type. The use of the OnType method enables you to constrain the override to a specified type with the dependency instead of being propagated throughout all types with the dependency.
Note
DependencyOverride will be in effect everywhere the specified dependency type shows up and there is an exact type match.
The two parameters for DependencyOverride, typeToConstruct and dependencyValue, specify the Type of the dependency to construct and the value to use for the parameter respectively. Overriding named dependencies is not supported. You should not try to override a named dependency if there is a default registration for that named dependency.
The values for dependency overrides are interpreted using the same rules used for values in constructor, property, and method injection. These rules are described in Registering Injected Parameter and Property Values. So for dependency overrides if you wish to supply an instance of the Type class to be used as a literal argument you must inject an InjectionParameter with the Type object, otherwise the override type is resolved in the container as an instance of the supplied type (see rule #2 in Registering Injection for Parameters, Properties, and Methods using InjectionMembers for details).
class Cars
{
public Cars(Type typeObject)
{ ... }
}
'Usage
Class Cars
Public Sub New(ByVal typeObject As Type)
...
End Sub
End Class
In the following example the override will apply to parameters of type Type, replacing the container's configuration with a resolved instance of type int.
container.Resolve<Cars>(new DependencyOverride(typeof(Type), typeof(int)));
'Usage
container.Resolve(Of Cars)(New DependencyOverride(GetType(Type), GetType(Integer)))
In the following example, the supplied instance of the Type class will be used as a literal argument and your intent is explicit.
container.Resolve<Cars>(new DependencyOverride(typeof(Type),
new InjectionParameter(typeof(int))));
'Usage
container.Resolve(Of Cars)(New DependencyOverride(GetType(Type), _
New InjectionParameter(GetType(Integer))))
Note
You cannot use the GenericParameters as values for overrides since they inherit from InjectionParameterValue and do not make sense when resolving. They only make sense when configuring an unbound generic type with RegisterType.
The following example creates an instance of DependencyOverride to override the given type with the given value. FirstObject is the type to override and overrideValue is the value used for the override.
var container = new UnityContainer()
.RegisterType<ObjectDependentOnFirstObject>(
new InjectionProperty("OtherObject"))
.RegisterType<FirstObject>(new InjectionConstructor());
// Use an arbitrary value for the overrideValue object
var overrideValue = new FirstObject(15);
var result = container.Resolve<ObjectDependentOnFirstObject>(
new DependencyOverride<FirstObject>(overrideValue));
'Usage
Dim container = New UnityContainer() _
.RegisterType(Of ObjectDependentOnFirstObject)( _
New InjectionProperty("OtherObject")) _
.RegisterType(Of FirstObject)(New InjectionConstructor())
' Use an arbitrary value for the overrideValue object
Dim overrideValue = New FirstObject(15)
Dim result = container.Resolve(Of ObjectDependentOnFirstObject)( _
New DependencyOverride(Of FirstObject)(overrideValue))
Where FirstObject and ObjectDependentOnFirstObject are defined as follows:
public class FirstObject
{
public FirstObject()
{ }
public FirstObject(int x)
{
X = x;
}
public int X { get; private set; }
}
public class ObjectDependentOnFirstObject
{
public FirstObject TestObject { get; set; }
public ObjectDependentOnFirstObject(FirstObject testObject)
{
TestObject = testObject;
}
public FirstObject OtherObject { get; set; }
}
'Usage
Public Class FirstObject
Public Sub New()
End Sub
Public Sub New(ByVal x__1 As Integer)
X = x__1
End Sub
Private _X As Integer
Public Property X() As Integer
Get
Return _X
End Get
Private Set(ByVal value As Integer)
_X = value
End Set
End Property
End Class
Public Class ObjectDependentOnFirstObject
Private _TestObject As FirstObject
Public Property TestObject() As FirstObject
Get
Return _TestObject
End Get
Set(ByVal value As FirstObject)
_TestObject = value
End Set
End Property
Public Sub New(ByVal testObject__1 As FirstObject)
TestObject = testObject__1
End Sub
Private _OtherTestObject As FirstObject
Public Property OtherObject() As FirstObject
Get
Return _OtherObject
End Get
Set(ByVal value As FirstObject)
_OtherObject = value
End Set
End Property
End Class
DependencyOverrides is a convenience form of DependencyOverride that lets you specify multiple dependency overrides in one shot rather than having to construct multiple objects. You must specify each type to be overridden and the value to use for the override. The following example will override FirstObject and SecondObject with overrideValue1 and overrideValue2, respectively.
var container = new UnityContainer() .RegisterType<ObjectDependentOnFirstObject>( new InjectionProperty("OtherObject")) .RegisterType<FirstObject>(new InjectionConstructor()); // Use an arbitrary value for the overrideValue objects var overrideValue1 = new FirstObject(15); var overrideValue2 = new FirstObject(25); var result = container.Resolve<ObjectDependentOnFirstObject>( new DependencyOverrides { {typeof(FirstObject),overrideValue1}, {typeof(SecondObject),overrideValue2}, } );
For Visual Basic .NET you must either use discrete DependencyOverride objects instead of the grouped one, or do something like the following:
'Usage Dim container = New UnityContainer() _ .RegisterType(Of ObjectDependentOnFirstObject)( _ New InjectionProperty("OtherObject")) _ .RegisterType(Of FirstObject)(New InjectionConstructor()) ' Use an arbitrary value for the overrideValue objects Dim overrideValue1 = New FirstObject(15) Dim overrideValue2 = New FirstObject(25) Dim overrides as new DependencyOverrides With overrides .Add("FirstObject ", overrideValue1) .Add("SecondObject ", overrideValue2) End With Dim result = container.Resolve(Of ObjectDependentOnFirstObject)(overrides)
DependencyOverride<T> is a convenience overload of DependencyOverride that lets you specify the dependency type using generic syntax. The following example uses a generic version of DependencyOverride that specifies the type the constructor is for as a generic parameter, type T (where T is a generic for the Type).
var result = container.Resolve<ObjectDependentOnT>( new DependencyOverride<T>(overrideValue));
'Usage Dim result = container.Resolve(Of ObjectDependentOnT)( _ New DependencyOverride(Of T)(overrideValue))
More information
For more information about the techniques discussed in this topic, see the following: