Microsoft Enterprise Library 5.0 |
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
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.
C# | Copy Code |
---|---|
var anInstance = container.Resolve<ClassCar>(new ParameterOverride("car", "new car").OnType<NewCar>()); |
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
// 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>()); |
Visual Basic | Copy Code |
---|---|
' 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.
C# | Copy Code |
---|---|
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:
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
class Customer { public customer(System.Int32 id, System.String name, IErrorLogger logger, IDataAccess db) { } } |
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
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:
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
container.RegisterType<TargetTypeForInjection>( new InjectionProperty("InjectedObject", defaultObject)); var result1 = container.Resolve<TargetTypeForInjection>( new PropertyOverride("InjectedObject", overrideValue)); |
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
var result = container.Resolve<TargetTypeForInjection>( new PropertyOverride("InjectedObject", overrideObject) .OnType<TargetType2>()); |
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
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:
Visual Basic | Copy Code |
---|---|
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).
C# | Copy Code |
---|---|
class Cars { public Cars(Type typeObject) { ... } } |
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
container.Resolve<Cars>(new DependencyOverride(typeof(Type), typeof(int))); |
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
container.Resolve<Cars>(new DependencyOverride(typeof(Type), new InjectionParameter(typeof(int)))); |
Visual Basic | Copy Code |
---|---|
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.
C# | Copy Code |
---|---|
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); |
Copy Code | |
---|---|
var result = container.Resolve<ObjectDependentOnFirstObject>( new DependencyOverride<FirstObject>(overrideValue)); |
Visual Basic | Copy Code |
---|---|
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:
C# | Copy Code |
---|---|
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; } } |
Visual Basic | Copy Code |
---|---|
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.
C# Copy Code 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:
Visual Basic Copy Code 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).
C# Copy Code var result = container.Resolve<ObjectDependentOnT>( new DependencyOverride<T>(overrideValue));
Visual Basic Copy Code Dim result = container.Resolve(Of ObjectDependentOnT)( _ New DependencyOverride(Of T)(overrideValue))