Using Unity Container Hierarchies
Using Unity Container Hierarchies
In
today’s post I’m going to explain why and
how to use the Unity container hierarchies.
As the subject suggest Unity application block
supports nested containers and allow you to
build containers hierarchies.
Why to Use Nested Containers
There are two reasons to use a nested containers:
- Control the scope of singleton object instances.
- Register different mapping for specific types.
Controlling the Scope of Singleton Object Instances
Singleton objects lifetime is managed by the Unity container. They are
kept in scope as long as the container isn’t disposed. In order to enable the
existence of two separate sets of the objects with different lifetime you
use a container hierarchy and manage each set in a different child container
of the parent container. Just remember that if the parent container is disposed
all its children are disposed as well.
The following code demonstrate how to use child containers to manage the lifetime
of a singleton instance:
IUnityContainer parentContainer = new UnityContainer();
parentContainer.RegisterType<ILogger, FileLogger>
(new ContainerControlledLifetimeManager());
// Create nested child container in parent container
IUnityContainer childContanier = parentContainer.CreateChildContainer();
childContanier.RegisterType<Database, SqlDatabase>
(new ContainerControlledLifetimeManager());
// Get an instance of type stored in parent container
ILogger logger = parentContainer.Resolve<ILogger>();
// Get an instance of type stored in child container
Database database = childContanier.Resolve<Database>();
// Dispose child container
childContanier.Dispose();
// Dispose parent container
parentContainer.Dispose();
In the example, after the creation of the database object you can either
use it and also use the logger object. After calling the Dispose method on the
child container you will be able to use only the logger object because
disposing the child container will end the lifetime of its generated objects.
Registering Different Mapping For Specific Types
Sometimes we have different dependency injection requirements for specific objects.
For example throughout the running application I want that ILogger will be resolved
to FileLogger but in some rare situations I need it to be resolved into DatabaseLogger.
In such cases one solution for the problem can be the use of container hierarchies.
You do it by registering the general mapping in the parent container and registering
the specific mapping in the child container. After the registration faze you’ll call the
Resolve method of the relevant container when needed.
So, what is the gain of using this technique instead of only registering the types with
different names and resolving them by name?
We gain the ability to go up the container chain if the registered type isn’t located in
the child container. That means that if calling the Resolve method on the child container
won’t locate the type needed the child container will send the request to the parent
container to be resolved.
The following code is an example for registering of different mapping to specific types:
IUnityContainer parentContainer = new UnityContainer();
var child1 = parentContainer.CreateChildContainer();
var child2 = parentContainer.CreateChildContainer();
parentContainer.RegisterType<ILogger, FileLogger>
(new ContainerControlledLifetimeManager());
child2.RegisterType<ILogger, CustomLogger>
(new ContainerControlledLifetimeManager());
// will result in CustomLogger registered in
// child2 container
var logger = child2.Resolve<ILogger>();
logger.Log("Test");
// will result in the FileLogger registered in the
// parent container
var logger2 = child1.Resolve<ILogger>();
logger.Log("Test");
Summary
To sum up the post, the container hierarchy feature is very useful in the
following situations - control the scope of singleton object instances and
register different mapping for specific types. I showed examples of how
to use the container hierarchies in every one of these situations.