Registering Types and Type Mappings

This topic explains how to register types in the container. Registering a type lets you configure how the container creates instances of the specified type. In general, you will create mappings between an interface and a type that implements the interface, or between a base class and a type that inherits that base class. However, you can register types in the container without creating a mapping.

The RegisterType method registers a type with the container. At the appropriate time, the container will build an instance of the type you specify. This could be in response to dependency injection through class attributes or when you call the Resolve method. The lifetime of the object it builds will correspond to the lifetime you specify in the parameters of the method. If you do not specify a value for the lifetime, the type is registered for a transient lifetime, which means that a new instance will be created on each call to Resolve.

This topic contains the following sections that explain use of the RegisterType method:

  • Registering an Interface or Class Mapping to a Concrete Type
  • Registering a Named Type
  • Registering Type Mappings with the Container
  • Using a Lifetime Manager with the RegisterType Method
  • Summary of the RegisterType Method Overloads
  • More Information

Registering an Interface or Class Mapping to a Concrete Type

This is the most common scenario for dependency injection using Unity. It involves registering a mapping between types such as an interface or a base class and a corresponding concrete class that implements or inherits from it.

First you must create a new instance of the UnityContainer class or obtain a reference to an existing instance so that you can call the RegisterType method of the container in which you want to register the mapping or type. The following example creates a new instance of the UnityContainer class by using the new operator.

IUnityContainer myContainer = new UnityContainer();
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()

You call the RegisterType method to specify the registered type as an interface or object type and the target type you want returned in response to a query for that type. The target type must implement the interface, or inherit from the class, that you specify as the registered type. The following code creates a default (unnamed) mapping using an interface as the dependency key.

myContainer.RegisterType<IMyService, CustomerService>();
'Usage
myContainer.RegisterType(Of IMyService, CustomerService)()

You can map a class or object type to a more specific class that inherits from it by using the same syntax but provide the inherited object as the registered type, as shown in the following example.

myContainer.RegisterType<MyServiceBase, DataService>();
'Usage
myContainer.RegisterType(Of MyServiceBase, DataService)()

Note

The registration controls how you will retrieve objects from the container. It is the type that you will specify when you call the Resolve or ResolveAll method to retrieve the concrete object instance.

You can create more than one registration or mapping for the same type, by creating a named (non-default) mapping by specifying a name as a parameter, as shown in the following example.

myContainer.RegisterType<IMyService, CustomerService>("Customers");
'Usage
myContainer.RegisterType(Of IMyService, CustomerService)("Customers")

Note

If the target class or object specifies any dependencies of its own, the instance returned will have these dependent objects injected automatically. For information about using constructor, property, or method call injection techniques, see Using Injection Attributes.

Registering a Named Type

You can create simple type registrations at run time using the Unity API. To register a type with a name, you simply specify the name as a parameter of the RegisterType call. The following example simply registers a named type in the container myContainer.

IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(MyEmailService), "MyBestEmail");
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(GetType(MyEmailService), "MyBestEmail")

Registering Type Mappings with the Container

Mapping types is useful for retrieving instances of different objects that implement the same specified interface or that inherit from the same specified base class. The target type for the mapping must inherit from or implement the base type or interface of the source. You can generate both default and named mappings for a type registration by using the generic overloads of the container methods.

// Register a default (un-named) type mapping
myContainer.RegisterType<IMyObject, MyRealObject>();
// Following code will return a new instance of MyRealObject
myContainer.Resolve<IMyObject>();

// Register a named type mapping
myContainer.RegisterType<IMyObject, MyRealObject>("MyMapping");
// Following code will return a new instance of MyRealObject
myContainer.Resolve<IMyObject>("MyMapping");
'Usage
' Register a default (un-named) type mapping
myContainer.RegisterType(Of IMyObject, MyRealObject)()
' Following code will return a new instance of MyRealObject
myContainer.Resolve(Of IMyObject)()

' Register a named type mapping
myContainer.RegisterType(Of IMyObject, MyRealObject)("MyMapping")
' Following code will return a new instance of MyRealObject
myContainer.Resolve(Of IMyObject)("MyMapping")

The following code registers a type mapping between an example interface named IRepository and a concrete type named SqlRepository that implements this interface. The code then registers a mapping for the SqlRepository type as an open generic type and shows how you can resolve a specific instance using the IRepository interface as the dependency identifier. For more information on generics see Registering Generic Parameters and Types.

public interface IRepository<TEntity> 
{
  TEntity GetById(int id);
}

public class SqlRepository<TEntity> : IRepository<TEntity>
{
  public TEntity GetById(int id) 
  {
    ... 
  }
}

IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(IRepository<>), typeof(SqlRepository<>));
IRepository<Customer> result = myContainer.Resolve<IRepository<Customer>>();
'Usage
Public Interface IRepository(Of TEntity)
  Function GetById(ByVal id As Integer) As TEntity
End Interface

Public Class SqlRepository(Of TEntity)
  Implements IRepository(Of TEntity)
  Public Function GetById(ByVal id As Integer) As TEntity _
                  Implements IRepository(Of TEntity).GetById
    ... 
  End Function
End Class

Dim myContainer As IUnityContainer = New UnityContainer()
myContainer.RegisterType(GetType(IRepository(Of )), GetType(SqlRepository(Of )))
Dim result As IRepository(Of Customer) = myContainer.Resolve(Of IRepository(Of Customer)())()

Using a Lifetime Manager with the RegisterType Method

You can also provide a lifetime manager when calling RegisterType. The LifetimeManager you specify when you register a type controls when object instances are created and disposed. If you do not specify a lifetime manager for your type registration, the object instances returned by the container have a transient lifetime. The container does not store a reference to the object, and creates a new instance of the type each time you call the Resolve method. If you want a different object lifetime, specify a lifetime manager when you call the RegisterType method.

For more information on lifetime managers see Understanding Lifetime Managers.

The most common scenario is to create an instance that behaves like a singleton, so that the container creates the object the first time you call Resolve and then returns the same instance for all subsequent calls to Resolve for as long as the container is in scope.****Register a singleton mapping by including an instance of the ContainerControlledLifetimeManager class in the parameters to the RegisterType method.

First you must create a new instance of the UnityContainer class or obtain a reference to an existing instance so that you can call the RegisterType method of the container in which you want to register the mapping or type.

IUnityContainer myContainer = new UnityContainer();
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()

The following example creates a default (unnamed) singleton mapping by adding new ContainerControlledLifetimeManager() to the RegisterType method parameters.

myContainer.RegisterType<IMyService, CustomerService>(new ContainerControlledLifetimeManager());
'Usage
myContainer.RegisterType(Of IMyService, CustomerService)(New ContainerControlledLifetimeManager())

You can also just register a specific type as a singleton by specifying as the registration type the concrete type you want returned in response to a query for that type. Include an instance of the ContainerControlledLifetimeManager class in the parameters to the RegisterType method. The following example creates a default (unnamed) singleton registration for the type CustomerService.

myContainer.RegisterType<CustomerService>(new ContainerControlledLifetimeManager());
'Usage
myContainer.RegisterType(Of CustomerService)(New ContainerControlledLifetimeManager())

You can create more than one registration using the same registered type, CustomerService, by creating a named (non-default) registration by specifying a name as a parameter. Each named registration uses a separate lifetime manager. In this example, calling container.Resolve<CustomerService>() and container.Resolve<CustomerService>("Customers") will result in two different instances. But calling container.Resolve<CustomerService>("Customers") multiple times will give the same instance each time.

myContainer.RegisterType<CustomerService>("Customers", 
                         new ContainerControlledLifetimeManager());
'Usage
myContainer.RegisterType(Of CustomerService)("Customers", _
                         New ContainerControlledLifetimeManager())

You can register more than one mapping for an object type, IMyService, CustomerService that will return a singleton using the registered type. You can do this by creating a named (non-default) registration by specifying a name as a parameter, as shown in the following example.

myContainer.RegisterType<IMyService, CustomerService>("Customers", 
                         new ContainerControlledLifetimeManager());
'Usage
myContainer.RegisterType(Of IMyService, CustomerService)("Customers", _
                         New ContainerControlledLifetimeManager())

The following example registers a default (unnamed) type mapping for the type MyRealObject with a per-thread lifetime by specifying the PerThreadLifetimeManager() class in the parameter list.

// Specify a default type mapping with an per thread lifetime
myContainer.RegisterType<IMyObject, MyRealObject>(new PerThreadLifetimeManager());
// Following code will return a reference to the object
myContainer.Resolve<IMyObject>();

// Specify a default type mapping with an externally-controlled lifetime
myContainer.RegisterType<IMyObject, MyRealObject>(new ExternallyControlledLifetimeManager());
// Following code will return a singleton instance of MyRealObject
// Container will hold only a weak reference to the object
myContainer.Resolve<IMyObject>();
'Usage
' Specify a default type mapping with an per thread lifetime
myContainer.RegisterType(Of IMyObject, MyRealObject)(New PerThreadLifetimeManager())
' Following code will return a reference to the object
myContainer.Resolve(Of IMyObject)()

' Specify a default type mapping with an externally-controlled lifetime
myContainer.RegisterType(Of IMyObject, MyRealObject)(New ExternallyControlledLifetimeManager())
' Following code will return a singleton instance of MyRealObject
' Container will hold only a weak reference to the object
myContainer.Resolve(Of IMyObject)()

The following code shows additional uses of the RegisterType method with a lifetime manager to specify the container behavior. It shows how you can generate both default and named mappings for a type registration.

IUnityContainer myContainer = new UnityContainer();

// Register a default (un-named) type mapping with a singleton lifetime
myContainer.RegisterType<IMyObject, MySingletonObject>(new ContainerControlledLifetimeManager());
// Following code will return a singleton instance of MySingletonObject
// Container will take over lifetime management of the object
myContainer.Resolve<IMyObject>();

// Register a named type mapping with a singleton lifetime
myContainer.RegisterType<IMyObject, MySingletonObject>("MyMapping", new ContainerControlledLifetimeManager());
// Following code will return a singleton instance of MySingletonObject
// Container will take over lifetime management of the object
myContainer.Resolve<IMyObject>();
'Usage
Dim myContainer As IUnityContainer = New UnityContainer()

' Register a default (un-named) type mapping with a singleton lifetime
myContainer.RegisterType(Of IMyObject, MySingletonObject)(new ContainerControlledLifetimeManager())
' Following code will return a singleton instance of MySingletonObject
' Container will take over lifetime management of the object
myContainer.Resolve(Of IMyObject)()

' Register a named type mapping with a singleton lifetime
myContainer.RegisterType(Of IMyObject, MySingletonObject)("MyMapping", new ContainerControlledLifetimeManager())
' Following code will return a singleton instance of MySingletonObject
' Container will take over lifetime management of the object
myContainer.Resolve(Of IMyObject)()

Summary of the RegisterType Method Overloads

The following table summarizes the method overloads you can use to register type mappings with the container at run time.

Method

Description

RegisterType<TFrom, TTo>(params InjectionMember[] injectionMembers)

Registers a default type mapping with the container so that it returns an instance of the type specified as TTo when a Resolve method requests an instance of the type TFrom. The injectionMembers parameter configures specific objects to be injected.

RegisterType<TFrom, TTo>(LifetimeManager lifetime, params InjectionMember[] injectionMembers)

Registers a default type mapping with the container so that it returns an instance of the type specified as TTo when a Resolve method requests an instance of the type TFrom. Also registers the specified LifetimeManager instance with the container to manage the lifetime of the returned object. The injectionMembers parameter configures specific objects to be injected.

RegisterType<TFrom, TTo>(String name, params InjectionMember[] injectionMembers)

Registers a named type mapping with the container so that it returns an instance of the type specified as TTo when a Resolve method requests an instance of the type TFrom with the specified name. If name is null, generates a default type mapping. Names are case sensitive. The injectionMembers parameter configures specific objects to be injected.

RegisterType<TFrom, TTo>(String name, LifetimeManager lifetime, params InjectionMember[] injectionMembers)

Registers a named type mapping with the container so that it returns an instance of the type specified as TTo when a Resolve method requests an instance of the type TFrom with the specified name. If name is null, generates a default type mapping. Names are case sensitive. Also registers the specified LifetimeManager instance with the container to manage the lifetime of the returned object. The injectionMembers parameter configures specific objects to be injected.

RegisterType<T>(LifetimeManager lifetime, params InjectionMember[] injectionMembers)

Creates a default type registration with the container so that it returns an instance of that type in response to a call from the Resolve method. Allows you to register a LifetimeManager with the container to manage the lifetime of the registered type. The injectionMembers parameter configures specific objects to be injected.

RegisterType<T>(String name, LifetimeManager lifetime, params InjectionMember[] injectionMembers)

Creates a named type registration with the container so that it returns an instance of that type in response to a call from the Resolve method with the specified name. Allows you to register a LifetimeManager with the container to manage the lifetime of the registered type. The injectionMembers parameter configures specific objects to be injected.

RegisterType(Type from, Type to, params InjectionMember[] injectionMembers)

Registers a default type mapping with the container so that it returns an instance of the type specified as to when a Resolve method requests an instance of the type from. The injectionMembers parameter configures specific objects to be injected.

RegisterType(Type from, Type to, String name, params InjectionMember[] injectionMembers)

Registers a named type mapping with the container so that it returns an instance of the type specified as to when a Resolve method requests an instance of the type from with the specified name. If name is null, generates a default type mapping. Names are case sensitive. The injectionMembers parameter configures specific objects to be injected.

RegisterType(Type from, Type to, LifetimeManager lifetime, params InjectionMember[] injectionMembers)

Registers a default type mapping with the container so that it returns an instance of the type specified as to when a Resolve method requests an instance of the type from. Also registers the specified LifetimeManager instance with the container to manage the lifetime of the returned object. The injectionMembers parameter configures specific objects to be injected.

RegisterType(Type from, Type to, String name, LifetimeManager lifetime, params InjectionMember[] injectionMembers)

Registers a named type mapping with the container so that it returns an instance of the type specified as to when a Resolve method requests an instance of the type from with the specified name. If name is null, generates a default type mapping. Names are case sensitive. Also registers the specified LifetimeManager instance with the container to manage the lifetime of the returned object. The injectionMembers parameter configures specific objects to be injected.

RegisterType(Type t, LifetimeManager lifetime, params InjectionMember[] injectionMembers)

Creates a default type registration with the container so that it returns an instance of that type in response to a call from the Resolve method. Allows you to register a LifetimeManager with the container to manage the lifetime of the registered type. The injectionMembers parameter configures specific objects to be injected.

RegisterType(Type t, String name, LifetimeManager lifetime params InjectionMember[] injectionMembers)

Creates a named type registration with the container so that it returns an instance of that type in response to a call from the Resolve method with the specified name. Allows you to register a LifetimeManager with the container to manage the lifetime of the registered type. The injectionMembers parameter configures specific objects to be injected.

The following example uses RegisterType to configure class methods for injection by the container.

IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<MyObject>(
    new InjectionConstructor(12, "Hello Unity!"),
    new InjectionProperty(“MyProperty”));
'Usage
Dim myContainer as IUnityContainer = New UnityContainer()
myContainer.RegisterType(Of MyObject)( _
   new InjectionConstructor(12, "Hello Unity!"), _
   new InjectionProperty(“MyProperty”))

More Information

For more information about the techniques discussed in this topic, see the following topics: