Dependency Injection Types and Mappings
Retired Content |
---|
This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. |
The latest Unity Application Block information can be found at the Unity Application Block site. |
The Unity Application Block container identifies registrations (type mappings) using a type and, optionally, a name. The type is an interface or a class (usually a base class) that the desired concrete object type implements or inherits. This identifies the mapping so that the container can retrieve the correct object type in response to a call to the Resolve or ResolveAll method. Where there is more than one mapping for the same type, the optional name differentiates these mappings and allows code to specify which of the mappings for that type to use.
The following sections of this topic describe how you can use dependency injection types and mappings:
- Interface Types as Dependency Identifiers
- Object Type Names as Dependency Identifiers
- Combining Dependency Identifiers and Registration Names
- Dependency Identifiers for Existing Objects and the BuildUp Method
- Resolving a List of All Registered Types by Dependency Identifier
Interface Types as Dependency Identifiers
As an example of using the overloads of the RegisterType and Resolve methods that accept an interface type name, the following code registers a mapping for an interface named IMyService and specifies that the container should return an instance of the CustomerService class (which implements the IMyService interface). In this case, the type IMyService identifies the registration type. Code that requests an instance of the type IMyService receives an instance of the CustomerService class. The following example uses the generic overloads of the container methods.
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IMyService, CustomerService>();
IMyService myServiceInstance = myContainer.Resolve<IMyService>();
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(Of IMyObject, CustomerService)()
Dim myServiceInstance As IMyService = myContainer.Resolve(Of IMyService)()
Alternatively, you can use the non-generic overloads of the methods. The following code achieves the same result.
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(IMyService), typeof(CustomerService));
IMyService myServiceInstance = (IMyService)myContainer.Resolve(typeof(IMyService));
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(GetType(IMyService), GetType(CustomerService))
Dim myServiceInstance As IMyService = myContainer.Resolve(GetType(IMyService))
Note
The provision of both generic and non-generic overloads of the Unity container methods ensures that the Unity Application Block can be used in languages that do not support generics. You can use either approach (the generic or the non-generic overloads) in your code and mix them as required. For example, you can register mappings using the generic overloads and then retrieve object instances using the non-generic overloads, and vice versa.
Object Type Names As Dependency Identifiers
When you need to register a mapping for a base class or other object type (instead of an interface), you use the overloads of the RegisterType and Resolve methods that accept object type names. The following examples show the use of the overloads of the RegisterType and Resolve methods that accept object type names as the registration identifier.
The following code registers a mapping for an object named MyBaseService and specifies that the container should return an instance of the CustomerService class (which inherits from the MyBaseService class). In this case, the type MyBaseService identifies the registration. Code that requests an instance of the type MyBaseService receives an instance of the CustomerService class.
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<MyBaseService, CustomerService>();
MyBaseService myServiceInstance = myContainer.Resolve<MyBaseService>();
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(Of MyBaseService, CustomerService)()
Dim myServiceInstance As MyBaseService = myContainer.Resolve(Of MyBaseService)()
Alternatively, you can use the non-generic overloads of the methods. The following code achieves the same result.
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(MyBaseService), typeof(CustomerService));
MyBaseService myServiceInstance = (MyBaseService)myContainer.Resolve(typeof(MyBaseService));
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(GetType(MyBaseService), GetType(CustomerService))
Dim myServiceInstance As MyBaseService = myContainer.Resolve(GetType(MyBaseService))
Combining Dependency Identifiers and Registration Names
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. 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")
Note
Registration (mapping) names are just strings, so they can contain spaces if required. However, they are case-sensitive. For example, the two 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 type or a type mapping more than once using the RegisterType method (in other words, if you register more than one type or type mapping that specifies the same types) only the last registration remains in the container and is applied when you execute the Resolve or ResolveAll method.
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
By default, the RegisterType method registers a type with a transient lifetime, which means that the container will not hold on to a reference to the objects it creates when you call the Resolve or ResolveAll method. Each time you call one of these methods, the container generates a new instance of the specified or mapped type. For more information about using lifetime managers to control the creation, lifetime, and disposal of objects, see Using Lifetime Managers. For information about how to create custom lifetime managers, see Creating Lifetime Managers.
Dependency Identifiers for Existing Objects and the BuildUp Method
The Unity container exposes overloads of the RegisterInstance method that allow you to register dependency injection mappings that return references to a single existing instance of an object. Each of these methods accepts a type parameter that identifies the object interface or type and an existing instance of the object. Optionally, you can provide a name where there is more than one registration for the same type.
The Unity container also exposes overloads of the BuildUp method that allow you to "wire up" the object on demand with all the dependencies applicable to it. The BuildUp method overloads accept a reference to an existing instance of the object. Optionally, you can provide a name where there is more than one registration for the same type.
For details of how to use registration types and names with the RegisterInstance and BuildUp methods, see Registering Existing Object Instances.
Resolving a List of All Registered Types by Dependency Identifiers
When you want to obtain a list of all the registered objects of a specific type, you can use the ResolveAll method. The two overloads of this method accept either an interface or a type name, and they return an instance of IEnumerable that contains references to all registered objects of that type that are not default mappings. The list returned by the ResolveAll method contains only named instance registrations.
Note
It is important to remember that you must register type mappings using a name in addition to the registration type (which identifies the registration) if you want to be able to retrieve a list of mapped types using the ResolveAll method. In other words, you must use overloads of the RegisterType and RegisterInstance methods that take a name (as a String) and the dependency type. This is "by design." The expectation is that you will either use only named mappings or use only default mappings.
The following example shows how you can retrieve a list of all registered types for a specific registration type.
// Create container and register types using a name for each one
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IMyService, DefaultService>();
myContainer.RegisterType<IMyService, DataService>("Data");
myContainer.RegisterType<IMyService, LoggingService>("Logging");
// Retrieve a list of non-default types registered for IMyService
// List will only contain the types DataService and LoggingService
IEnumerable<IMyService> serviceList = myContainer.ResolveAll<IMyService>();
'Usage
' Create container and register types using a name for each one
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(Of IMyService, DefaultService)()
myContainer.RegisterType(Of IMyService, DataService)("Data")
myContainer.RegisterType(Of IMyService, LoggingService)("Logging")
' Retrieve a list of non-default types registered for IMyService
' List will only contain the types DataService and LoggingService
Dim serviceList As IEnumerable(Of IMyService) = myContainer.ResolveAll(Of IMyService)
Alternatively, you can use the non-generic methods of the container to achieve the same result, except that the return value this time is an IEnumerable list of type Object.
// Create container and register types using a name for each one
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(MyServiceBase), typeof(DefaultService));
myContainer.RegisterType(typeof(MyServiceBase), typeof(DataService), "Data");
myContainer.RegisterType(typeof(MyServiceBase), typeof(LoggingService), "Logging");
// Retrieve a list of non-default types registered for MyServiceBase
// List will only contain the types DataService and LoggingService
foreach(Object mapping in myContainer.ResolveAll(typeof(MyServiceBase)))
{
MyServiceBase myService = (MyServiceBase)mapping;
}
'Usage
' Create container and register types using a name for each one
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(GetType(MyServiceBase), GetType(DefaultService))
myContainer.RegisterType(GetType(MyServiceBase), GetType(DataService), "Data")
myContainer.RegisterType(GetType(MyServiceBase), GetType(LoggingService), "Logging")
' Retrieve a list of non-default types registered for MyServiceBase
' List will only contain the types DataService and LoggingService
For Each mapping As Object In myContainer.ResolveAll(GetType(MyServiceBase))
Dim myService As MyServiceBase = CType(mapping, MyServiceBase)
Next