다음을 통해 공유


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: