Resolving an Object by Type and Registration Name
Unity provides a method named Resolve that you can use to resolve an object by type, and optionally by providing a registration name. Registrations that specify a name are referred to as named registrations. This topic describes how to use the Resolve method to resolve types and mappings registered as named registrations. For information about resolving default registrations, see Resolving an Object by Type.
The Resolve Method Overloads for Named Registrations
The following table describes the overloads of the Resolve method that return instances of objects based on named registrations and mappings with the container. The API for the Unity container contains both generic and non-generic overloads of this method so that you can use it with languages that do not support the generics syntax.
Method |
Description |
---|---|
Resolve<T>(string name, params ResolverOverride[] resolverOverrides) |
Returns an instance of the type registered with the container as the type T with the specified name and where params provide any constructor overrides for the Resolve calls. Names are case sensitive. |
Resolve(Type t, string name, params ResolverOverride[] resolverOverrides) |
Returns an instance of the default type registered with the container as the type t with the specified name and where params provide any constructor overrides for the Resolve calls. Names are case sensitive. |
Note
If you call the Resolve method and specify a name as well as the registration type, and there is no mapping registered for that type and name, the container will attempt to create an instance of the type you resolved. If that type is a base class or interface, which cannot be constructed, Unity will raise an exception.
Registration (mapping) names are just strings, so they can contain spaces if required. However, they are case sensitive. For example, the names Mymapping and MyMapping will refer to two different registration mappings.
You can use the same name for different registrations if they register different object types. The key used to retrieve a registration is effectively a combination of the registered type and the name.
If you register a named type or a named type mapping more than once using the same type and name, only the last registration remains in the container and is applied when you execute the Resolve method.
Using the Resolve Method with Named Registrations
If you need to register multiple mappings for the same type, you can specify a name to differentiate each mapping. Then, to retrieve an object of the appropriate type, you specify the name and the registered type. Typically you will register a type mapping between an interface and a concrete type that implements it, or between a base class and a concrete type that inherits it.
The following examples show how you can retrieve concrete instances of registered objects from a Unity container using the Resolve method when you have registered one or more mappings for a type and differentiated them by name. The examples use the run-me methods of the container to register the types it will resolve. For more information about how you can configure Unity with type registrations and mappings, see Configuring Unity.
Resolving Types Registered as Interfaces
The following code demonstrates how you can register two mappings for the same interface class and have the container return the appropriate object type depending on the type and name you specify in the call to the Resolve method. The following example uses the generic overloads of the container methods (though you can also use the non-generic method overloads).
// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IMyService, DataService>("Data");
myContainer.RegisterType<IMyService, LoggingService>("Logging");
// Retrieve an instance of each type
IMyService myDataService = myContainer.Resolve<IMyService>("Data");
IMyService myLoggingService = myContainer.Resolve<IMyService>("Logging");
'Usage
' Create container and register types
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(Of IMyService, DataService)("Data")
myContainer.RegisterType(Of IMyService, LoggingService)("Logging")
' Retrieve an instance of each type
Dim myDataService As IMyService = myContainer.Resolve(Of IMyService)("Data")
Dim myLoggingService As IMyService = myContainer.Resolve(Of IMyService)("Logging")
Resolving Types Registered as Base Classes
The following code demonstrates how you can register two mappings for the same base or other class using the overloads of the RegisterType and Resolve methods that accept type names, and then have the container return the appropriate object type depending on the type and name you specify in the call to the Resolve method. This example uses the non-generic overloads of the container methods (though you can also use generic method overloads).
// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(MyServiceBase), typeof(DataService), "Data");
myContainer.RegisterType(typeof(MyServiceBase), typeof(LoggingService), "Logging");
// Retrieve an instance of each type
MyServiceBase myDataService = (MyServiceBase)myContainer.Resolve(typeof(MyServiceBase), "Data");
MyServiceBase myLoggingService = (MyServiceBase)myContainer.Resolve(typeof(MyServiceBase), "Logging");
'Usage
' Create container and register types
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(GetType(MyServiceBase), GetType(DataService), "Data")
myContainer.RegisterType(GetType(MyServiceBase), GetType(LoggingService), "Logging")
' Retrieve an instance of each type
Dim myDataService As MyServiceBase = myContainer.Resolve(GetType(MyServiceBase), "Data")
Dim myLoggingService As MyServiceBase = myContainer.Resolve(GetType(MyServiceBase), "Logging")
Note
If the target class or object specifies any dependencies of its own, using constructor, property, or method call injection attributes, the instance returned will have these dependent objects injected automatically.
By default, the RegisterType method registers a type with a transient lifetime, which means that the container will not hold onto a reference to the objects it creates when you call the Resolve method. Each time you call one of these methods, the container generates a new instance of the specified or mapped type. However, you can use lifetime managers to control the creation, lifetime, and disposal of objects, if required.
Resolving Generic Types by Name
You can also resolve generic types by name, just as you do with non-generic types.
Note
You cannot resolve unbound generic types. When an instance is created by Unity, concrete type arguments replace all of the generic type parameters.
For more information see the "Resolving Generic Types" section in Resolving an Object by Type.
You can specify the parameter that defines the base class or interface type you to resolve as the actual type by using the Resolve method generic overload. The following example assumes that you have registered a named mapping between the IMyService type and a concrete type named MyDataService. The Resolve method will return the named instance, Personal, of the MyDataService class.
var myInstance = myContainer.Resolve<IMyService>("Personal");
'Usage
Dim myInstance = myContainer.Resolve(Of IMyService)("Personal")
More Information
For more information about the techniques discussed in this topic, see the following:
Resolving Generic Types
You resolve generic types in much the same way as you resolve non-generic types. The primary difference is with unbound types. The specification of the type arguments depend on the definition of the mapped type or the type you are resolving:
If the mapped type or the type you are resolving is a bound type, you can only resolve an instance of the type using the defined type arguments. For example, if the mapped type has type arguments of type string and DateTime, you must specify these in the call to the Resolve method.
If the mapped type or the type you are resolving is an unbound type, you can resolve an instance of the type using any types for the type arguments. The target class must be able to process arguments of the type you specify. For example, if one of the type arguments you specify is the type Boolean, the class must be able to handle Boolean values for that argument and not attempt to parse the value into a DateTime instance.
Note
You cannot resolve unbound generic types. You can register an unbound generic type but you must specify a mapping to a concrete type that Unity can resolve.
The examples in this section use the following aliases and registrations:
<!-- Generic type aliases -->
<alias alias="IMyClosedInterface" type=
"TypeMappingsExamples.MyTypes.IMyInterface`2[
System.String,System.DateTime], TypeMappingsExamples" />
<alias alias="IMyUnboundInterface" type="TypeMappingsExamples.
MyTypes.IMyInterface`2, TypeMappingsExamples" />
<alias alias="MyClosedClass" type="TypeMappingsExamples.
MyTypes.MyClass`2[System.String,System.DateTime], TypeMappingsExamples" />
<alias alias="MyUnboundClass" type="TypeMappingsExamples.
MyTypes.MyClass`2, TypeMappingsExamples" />
<container name="container1">
<!-- Generic type mappings -->
<register type="IMyClosedInterface" mapTo="MyClosedClass" name="Closed(String,DateTime)ToClosed(String,DateTime)" />
<register type="IMyUnboundInterface" mapTo="MyUnboundClass" name="UnboundToUnbound" />
<register type="IMyUnboundInterface" mapTo="MyClosedClass" name="UnboundToClosed(String,DateTime)" />
</container>
The following example resolves an instance using closed generic types.
// Resolve closed IMyInterface type using type parameters String and DateTime.
var result1 = myContainer.Resolve<IMyInterface<string, DateTime>>(
"Closed(String,DateTime)ToClosed(String,DateTime)");
'Usage
' Resolve the closed IMyInterface type using type parameters String and DateTime.
Dim result1 = myContainer.Resolve(Of IMyInterface(Of String, DateTime))( _
"Closed(String,DateTime)ToClosed(String,DateTime)")
The result is resolved through the mapping between the closed types, and is valid because the combination of type arguments supplied in the call to the Resolve method matches those for the mapping of the closed types. Unity returns the following result:
'MyClass`2[System.String,System.DateTime]'
The following example resolves instances for unbound generic types.
// Resolve unbound IMyInterface type using type parameters Integer and Decimal.
var result2 = myContainer.Resolve<IMyInterface<int, decimal>>(
"UnboundToUnbound");
// Resolve unbound IMyInterface type using type parameters String and DateTime.
var result3 = myContainer.Resolve<IMyInterface<string, DateTime>>(
"UnboundToClosed(String,DateTime)");
'Usage
' Resolve the unbound IMyInterface type using type parameters Integer and Decimal.
Dim result2 = myContainer.Resolve(Of IMyInterface(Of Integer, Decimal))( _
"UnboundToUnbound")
' Resolve the unbound IMyInterface type using type parameters String and DateTime.
Dim result3 = myContainer.Resolve(Of IMyInterface(Of String, DateTime))( _
"UnboundToClosed(String,DateTime)")
The examples return the following results:
Resolving with the mapping 'UnboundToUnbound'
- Unity returns 'MyClass`2[System.Int32,System.Decimal]'
Resolving IMyInterface using the mapping 'UnboundToClosed(String,DateTime)'
- Unity returns 'MyClass`2[System.String,System.DateTime]'
The UnboundToUnbound example returns a closed instance. The call to the Resolve method specifies the use of the mapping between the unbound types. However, as the call to this method includes the definition of the type arguments, Unity will resolve an instance of the closed type. The types used for the type arguments in the call to the Resolve method can be any type that the target class can process.
More Information
For more information about the techniques discussed in this topic, see the following: