Code through the pain Ladislav Mrnka's professional blog about software development

7Mar/116

If you have been using inversion of control containers for a while you have most probably used some object lifetime management. The lifetime management enables reuse of existing object instances for subsequent resolution. It should be also responsible for controlling how the container will release resolved instances.

Unity offers lifetime management as classes derived from LifetimeManager. Lifetime managers in Unity are created once for each type's registration (there is an exception which I will discuss later). Every time a UnityContainer wants to create a new object instance when resolving a type it first checks with that type's lifetime manager if an instance is available. If no instance is available, the container creates an instance based on the configured constructor and passes that instance to the lifetime manager.

The following text discusses built-in lifetime managers, their behavior and usage.

LifetimeManager

The LifetimeManager is an abstract class implementing the ILifetimePolicy interface. This class is used as the parent for all built-in and custom lifetime managers. It defines three methods for instance lifetime management:

  • GetValue - returns a stored object instance already associated with lifetime manager.
  • SetValue - stores a new object instance in the lifetime manager.
  • RemoveValue - removes stored instance from lifetime manager. Default implementation of UnityContainer does not call this method but you can call it by the custom container's extension.

Lifetime in Unity is not related to lifetime of resolved instance but to the period of time when containers know about resolved instances. Unity 2.0 offers six built-in lifetime managers, but only two of them handle instance release and disposing. So, only two built-in lifetime managers satisfy the initial definition of lifetime management.

Examples use this test class:

namespace LifetimeManagement
{
    public interface IExample : IDisposable
    {
        void SayHello();
    }

    public class Example : IExample
    {
        private bool _disposed = false;
        private readonly Guid _key = Guid.NewGuid();

        public void SayHello()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("Example",
                    String.Format("{0} is already disposed!", _key));
            }

            Console.WriteLine("{0} says hello in thread {1}!", _key,
                Thread.CurrentThread.ManagedThreadId);
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
            }
        }
    }
}

TransientLifetimeManager

TransientLifetimeManager is the default lifetime manager used when no other lifetime manager is specified for a resolved type. The implementation of this lifetime manager is empty, which means that the container will return new object instances each time it resolves the type. The container does not track instances created with this lifetime manager and it also does not handle their disposal.

The type registration with TransientLifetimeManager in the configuration file:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <alias alias="IExample" type="LifetimeManagement.IExample, LifetimeManagement" />
  <alias alias="Example" type="LifetimeManagement.Example, LifetimeManagement" />
  <container>
    <register name="implicitReg" type="IExample" mapTo="Example" />
    <register name="explicitReg" type="IExample" mapTo="Example">
      <lifetime type="transient" />
    </register>
  </container>
</unity>

The alternative type registration with the fluent API:

var container = new UnityContainer();
container
    .RegisterType(typeof(IExample), typeof(Example), "implicitReg")
    .RegisterType(typeof(IExample), typeof(Example), "explicitReg",
        new TransientLifetimeManager());

The example using transient instances:

IExample example;
using (IUnityContainer container = GetContainer(ExampleContainer))
{
    // Each SayHello gets its own instance
    container.Resolve<IExample>("implicitReg").SayHello();
    container.Resolve<IExample>("implicitReg").SayHello();
    container.Resolve<IExample>("explicitReg").SayHello();
    example = container.Resolve<IExample>("explicitReg");
}
// Container is disposed but Example instance still lives
// => all previously created instances weren't disposed!
SayHello(example);

The example's output:

c6370d1b-15e3-4d92-8620-6f1182764c2d says hello in thread 1!
70b77d4d-8e4b-4ecd-a6da-b49ade646fc1 says hello in thread 1!
d4ca7c6e-f494-4835-acb1-954db9d7e095 says hello in thread 1!
91a1afc8-c909-4ef7-ac73-7e3740896e54 says hello in thread 1!

ContainerControlledLifetimeManager

ContainerControlledLifetimeManager provides a singleton instance of a registered type per UnityContainer and all its subcontainers.  Only the first resolution of a configured type creates a new instance, which is stored and reused for the container's whole lifetime. This is the only built-in lifetime manager which internally calls the RemoveValue method. The method is called when the lifetime manager is disposed (when container is disposed). It is also the only built-in lifetime manager which disposes stored instances of resolved types (implementing IDisposable).

Be aware that the singleton instance is related to one registration. If you create multiple registrations of the same type with new instance of this lifetime manager you will have one singleton instance for each registration.

The type registration with ContainerControlledLifetimeManager in the configuration file:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <alias alias="IExample" type="LifetimeManagement.IExample, LifetimeManagement" />
  <alias alias="Example" type="LifetimeManagement.Example, LifetimeManagement" />
  <container>
    <register name="singletonReg" type="IExample" mapTo="Example">
      <lifetime type="singleton" />
    </register>
  </container>
</unity>

The alternative type registratio with the fluent API:

var container = new UnityContainer();
container
    .RegisterType(typeof(IExample), typeof(Example), "singletonReg",
        new ContainerControlledLifetimeManager());

The example using singleton instance:

IExample example;
using (IUnityContainer container = GetContainer(ExampleContainer))
{
    IUnityContainer firstSub = null;
    IUnityContainer secondSub = null;

    try
    {
        firstSub = container.CreateChildContainer();
        secondSub = container.CreateChildContainer();

        // All containers share same instance
        // Each resolve returns same instance
        firstSub.Resolve<IExample>("singletonReg").SayHello();
        // Run one resolving in other thread and still receive same instance
        var thread = RunInOtherThread(
                         () => secondSub.Resolve<IExample>("singletonReg").SayHello());
        container.Resolve<IExample>("singletonReg").SayHello();
        example = container.Resolve<IExample>("singletonReg");
        thread.Join();
    }
    finally
    {
        if (firstSub != null) firstSub.Dispose();
        if (secondSub != null) secondSub.Dispose();
    }
}
// Exception - instance has been disposed with container
example.SayHello();

The example's output:

88777f22-1c7e-4628-8542-86855a9c56a6 says hello in thread 1!
88777f22-1c7e-4628-8542-86855a9c56a6 says hello in thread 1!
88777f22-1c7e-4628-8542-86855a9c56a6 says hello in thread 3!
88777f22-1c7e-4628-8542-86855a9c56a6 is already disposed!
Object name: 'Example'.

HierarchicalLifetimeManager

HierarchicalLifetimeManager class derives from ContainerControlledLifetimeManager. It shares all behaviors of its parent class including the internal call to RemoveValue and disposing stored instances of resolved types. The difference between these lifetime managers is related to using subcontainers. ContainerControlledLifetimeManager shares the same resolved instance among all subcontainers. HierarchicalLifetimeManager shares the same resolved instance only in a single container, subcontainers will hold their own resolved instance of resolved object.

The type registration with HierarchicalLifetimeManager in the configuration file:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <alias alias="IExample" type="LifetimeManagement.IExample, LifetimeManagement" />
  <alias alias="Example" type="LifetimeManagement.Example, LifetimeManagement" />
  <container>
    <register name="hierarchicalReg" type="IExample" mapTo="Example">
      <lifetime type="hierarchical" />
    </register>
  </container>
</unity>

The alternative type registration with the fluent API:

var container = new UnityContainer();
container
    .RegisterType(typeof(IExample), typeof(Example), "hierarchicalReg",
                  new HieararchicalLifetimeManager());

The example using per-container singleton instaces:

IExample example;
using (IUnityContainer container = GetContainer(ExampleContainer))
{
    IUnityContainer firstSub = null;
    IUnityContainer secondSub = null;

    try
    {
        firstSub = container.CreateChildContainer();
        secondSub = container.CreateChildContainer();

        // Each subcontainer has its own instance
        firstSub.Resolve<IExample>("hierarchicalReg").SayHello();
        secondSub.Resolve<IExample>("hierarchicalReg").SayHello();
        container.Resolve<IExample>("hierarchicalReg").SayHello();
        example = firstSub.Resolve<IExample>("hierarchicalReg");
    }
    finally
    {
        if (firstSub != null) firstSub.Dispose();
        if (secondSub != null) secondSub.Dispose();
    }

    // Exception - instance has been disposed with subcontainer
    example.SayHello();
}

The example's output:

d97947d9-d8f5-41ec-9a62-2a71c0a168dc says hello in thread 1!
8f3e42bf-df9b-4e12-afb6-bc653212fa69 says hello in thread 1!
c57f5ee5-9897-4102-ac10-e5cec35b9e8c says hello in thread 1!
d97947d9-d8f5-41ec-9a62-2a71c0a168dc is already disposed!
Object name: 'Example'.

ExternallyControlledLifetimeManager

ExternallyControlledLifetimeManager is a lifetime manager used for object instances controlled outside of UnityContainer. This lifetime manager internally only stores a WeakReference to the provided object instance so there must be another strong reference to the instance outside of UnityContainer, otherwise the current instance will be collected next time the garbage collector runs. A new instance of the resolved type is created each time the weak reference is dead.  This container can be used for instances created outside of our code and registered with call to RegisterInstance. For example, instances returned from third party libraries can be registered with this lifetime manager and used in dependency injection resolution of our own types.

The type registration with ExternallyControlledLifetimeManager in the configuration file:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <alias alias="IExample" type="LifetimeManagement.IExample, LifetimeManagement" />
  <alias alias="Example" type="LifetimeManagement.Example, LifetimeManagement" />
  <container>
    <register name="externalReg" type="IExample" mapTo="Example">
      <lifetime type="external" />
    </register>
  </container>
</unity>

The alternative type registration with the fluent API:

var container = new UnityContainer();
container
    .RegisterType(typeof(IExample), typeof(Example), "externalReg",
        new ExternallyControlledLifetimeManager());

The example using externally controlled instances:

IExample example;
using (IUnityContainer container = GetContainer(ExampleContainer))
{
    // Same instance is used in following SayHellos
    container.Resolve<IExample>("externalReg").SayHello();
    container.Resolve<IExample>("externalReg").SayHello();
    // Run garbate collector. Stored Example instance will be released
    // beacuse there is no reference for it and LifetimeManager holds
    // only WeakReference
    GC.Collect();
    // Object stored targeted by WeakReference was released => New instance is created!
    container.Resolve<IExample>("externalReg").SayHello();
    example = container.Resolve<IExample>("externalReg");
}

// Container does not control instance lifetime
example.SayHello();

The example's output:

c6a99d69-3789-4d69-a2d6-24fd6897d92d says hello in thread 1!
c6a99d69-3789-4d69-a2d6-24fd6897d92d says hello in thread 1!
617b1054-d521-404b-b2a3-9c7ab134c515 says hello in thread 1!
617b1054-d521-404b-b2a3-9c7ab134c515 says hello in thread 1!

PerThreadLifetimeManager

PerThreadLifetimeManager provides a "per-thread singleton". All instances are internally stored in a ThreadStatic collection. The container does not track instances created with this lifetime manager and it also does not handle their disposal. I will further discuss this container in a separate blog post because its internal implementation is incorrect and using it can cause problems.

The type registration with PerThreadLifetimeManager in the configuration file:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <alias alias="IExample" type="LifetimeManagement.IExample, LifetimeManagement" />
  <alias alias="Example" type="LifetimeManagement.Example, LifetimeManagement" />
  <container>
    <register name="perthreadReg" type="IExample" mapTo="Example">
      <lifetime type="perthread" />
    </register>
  </container>
</unity>

The alternative type registration with the fluent API:

var container = new UnityContainer();
container
    .RegisterType(typeof(IExample), typeof(Example), "perthreadReg",
        new PerThreadLifetimeManager());

The example using per-thread singleton instances:

IExample example;
using (IUnityContainer container = GetContainer(ExampleContainer))
{
    Action<int> action = delegate(int sleep)
        {
            // Both calls use same instance per thread
            container.Resolve<IExample>("perthreadReg").SayHello();
            Thread.Sleep(sleep);
            container.Resolve<IExample>("perthreadReg").SayHello();
        };

    var thread1 = RunInOtherThread(action, 50);
    var thread2 = RunInOtherThread(action, 50);
    thread1.Join();
    thread2.Join();
    example = container.Resolve<IExample>("perthreadReg");
}

// Container is disposed but example instance still lives
// => all previously created instances weren't disposed!
example.SayHello();

The example's output:

bc574cd5-fe90-423a-9873-7c8490cf900c says hello in thread 4!
5d7a1ed6-2346-499f-a7d0-c033abf342af says hello in thread 5!
5d7a1ed6-2346-499f-a7d0-c033abf342af says hello in thread 5!
bc574cd5-fe90-423a-9873-7c8490cf900c says hello in thread 4!
45d402e5-408c-46a3-a10f-ada2dd1fe932 says hello in thread 1!

PerResolveLifetimeManager

PerResolveLifetimeManager is a special built-in lifetime manager because Unity uses separate logic when dealing with types registered with per-resolve lifetime. This is the only lifetime manager which is created each time the UnityContainer starts resolving a type. This lifetime manager enables reusing resolved instance when whole object graph of dependencies is created. The container does not track instances created with this lifetime manager and it also does not handle their disposing. I will discuss examples of this lifetime manager in a separate blog post.

Posted on March 7, 2011 by Ladislav Mrnka
Filed under: Enterprise library
Leave a comment
Comments (6) Trackbacks (5)
  1. Cheers for the useful information, looking forward to reading about the PerResolveLifetimeManager.

  2. Thanks for explaining it so clearly, very useful.

  3. Thank you for your Explain!I have a problem in my Project of MVC,now I have no way to resolve,my project run a period time while it raise a Exception which prStore update, insert, or delete statement affected an unexpected number of rows ({0}). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entriesompts “,Can you help me ?I will appreciate

  4. Great article. Had one question, is there a way by which we can resolve an instance of a particular class in method and share between resolving dependent resource in that method only. If we make second call to the method it may invoke new intance and share between resolving dependent resources. In other words, what life time manager should we use to restrict the instance in the scope of the method but still share that instance between different resolves inside that method?

    Thanks!

  5. Great article but what ever happened to the follow up blog posts you where planning on writing for PerThreadLifeTimeManager and PerResolveLifeTimeManager. I am interested in reading more about what you have to say on Unity and its LifeTimeManagers.


Leave a comment

(required)