Export (0) Print
Expand All

Using Lifetime Managers

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 container manages the creation and resolution of objects based on a lifetime you specify when you register the type of an existing object or on the default lifetime if you do not specify a lifetime manager for it to use.

When you register a type using the RegisterType method, the default behavior is for the container to use a transient lifetime manager. It creates a new instance of the registered, mapped, or requested type each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. The container does not store a reference to the object. However, when you want singleton behavior for objects Unity creates, the container must store a reference to these objects. It also takes over management of the lifetime of the objects.

Unity uses specific types that inherit from the LifetimeManager base class (collectively referred to as lifetime managers) to control how it stores references to object instances and how the container disposes of these instances.

When you register an existing object using the RegisterInstance method, the default behavior is for the container to take over management of the lifetime of the object you pass to this method using the ContainerControlledLifetimeManager. This means that the existing object remains in scope as long as the container is in scope, and it is disposed when the container goes out of scope and is garbage-collected or when code explicitly disposes the container. You can also use this lifetime manager with the RegisterType method to specify that Unity should manage the object as a singleton instance.

The Unity Application Block includes three lifetime managers that you can use directly in your code, but you can create your own lifetime managers to implement specific lifetime scenarios. Unity includes the following lifetime managers:

  • ContainerControlledLifetimeManager. Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects. Unity uses this lifetime manager by default for the RegisterInstance method if you do not specify a different lifetime manager. If you want singleton behavior for an object that Unity creates when you use the RegisterType method, you must explicitly specify this lifetime manager. The behavior is as follows:
    • If you used the RegisterType method to register a type, Unity creates a new instance of the registered type during the first call to the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. Subsequent requests return the same instance.
    • If you used the RegisterInstance method to register an existing object, Unity returns this instance every time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes.
  • ExternallyControlledLifetimeManager. This lifetime manager allows you to register type mappings and existing objects with the container so that it maintains only a weak reference to the objects it creates when you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes based on attributes or constructor parameters within that class. Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. However, the container does not hold onto a strong reference to the object after it creates it, which means that the garbage collector can dispose of the object if no other code is holding a strong reference to it.
  • PerThreadLifetimeManager. Unity returns, on a per-thread basis, the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects on a per-thread basis. PerThreadLifetimeManager returns different objects from the container for each thread. The behavior is as follows:
    • If you used the RegisterType method to register a type, Unity creates a new instance of the registered type the first time the type is resolved in a specified thread, either to answer a call to the Resolve or ResolveAll methods for the registered type or to fulfill a dependency while resolving a different type. Subsequent resolutions on the same thread return the same instance.
    • Using the RegisterInstance method to register an existing object results in the same behavior as if you just registered the lifetime container with RegisterType. Therefore, it is recommended that you do not use the RegisterInstance method to register an existing object when using the PerThreadLifetimeManager.
    • PerThreadLifetimeManager returns the object desired or permits the container to create a new instance if no such object is currently stored for the current thread. A new instance is also created if called on a different thread than the one that set the value. This lifetime manager does not dispose the instances it holds.

Ff647854.note(en-us,PandP.10).gifNote:
For information about how you can create your own custom lifetime managers, see Creating Lifetime Managers.


The following sections show some examples of how you can use lifetime managers with the RegisterType and RegisterInstance methods to specify the container behavior:

The following code shows how you can use 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. This example uses the generic overloads of the container methods.

IUnityContainer myContainer = new UnityContainer();

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

// Register a named type mapping with a transient lifetime
myContainer.RegisterType<IMyObject, MyRealObject>("MyMapping");
// Following code will return a new instance of MyRealObject
myContainer.Resolve<IMyObject>("MyMapping");

// Specify a default type mapping with an per thread lifetime
myContainer.RegisterType<IMyObject, MyRealObject>(new PerThreadLifetimeManager());
// Following code will return a singleton instance of MyRealObject
// Container will hold only a weak 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>();

// Same as above, but with a name for the registration
myContainer.RegisterType<IMyObject, MyRealObject>("MyMapping", new ExternallyControlledLifetimeManager());
// Following code will return a singleton instance of MyRealObject
// Container will hold only a weak reference to the object
myContainer.Resolve<IMyObject>("MyMapping");

// 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>();

// Register a type to have a singleton lifetime without mapping the type
// Uses the container only to implement singleton behavior
myContainer.RegisterType<MySingletonObject>(new ContainerControlledLifetimeManager());
// Following code will return a singleton instance of MySingletonObject
// Container will take over lifetime management of the object
myContainer.Resolve<MySingletonObject>();

// Same as above, but specify a name for the registration
myContainer.RegisterType<MySingletonObject>("MyMapping", new ContainerControlledLifetimeManager());
// Following code will return a singleton instance of MySingletonObject
// Container will take over lifetime management of the object
myContainer.Resolve<MySingletonObject>("MyMapping");

The following code shows how you can use the RegisterInstance method with a lifetime manager to specify the container behavior. It also shows how you can generate both default and named mappings when you register an existing object. This example uses the generic overloads of the container methods.

IUnityContainer myContainer = new UnityContainer();

// Register an existing object as a default (un-named) registration with 
// the default container-controlled lifetime. 
myContainer.RegisterInstance<IMyObject>(MyRealObject);
// Following code will return a singleton instance of MyRealObject
// Container will take over lifetime management of the object
myContainer.Resolve<IMyObject>();

// Register an existing object as a named registration with the default
// container-controlled lifetime.
myContainer.RegisterInstance<IMyObject>("MySingleton", MyRealObject);
// Following code will return a singleton instance of MyRealObject
// Container will take over lifetime management of the object
myContainer.Resolve<IMyObject>("MySingleton");

// Same as above, but specify the default lifetime manager
myContainer.RegisterInstance<IMyObject>("MySingleton", MyRealObject, new ContainerControlledLifetimeManager());
// Following code will return a singleton instance of MyRealObject
// Container will take over lifetime management of the object
myContainer.Resolve<IMyObject>("MySingleton");

// Register an existing object as a default (un-named) registration 
// with an externally controlled lifetime.
myContainer.RegisterInstance<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>();

// Register an existing object as a named registration 
// with an externally controlled lifetime.
myContainer.RegisterInstance<IMyObject>("MySingleton", 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>("MySingleton");

// Register an existing object as a named registration 
// with a per thread lifetime.
myContainer.RegisterInstance<IMyObject>("MySingleton", MyRealObject, new PerThreadLifetimeManager());
// Following code will return a singleton instance of MyRealObject
// Container will hold only a weak reference to the object
myContainer.Resolve<IMyObject>("MySingleton");


Show:
© 2014 Microsoft