Unity lifetime management for IDisposable, part 1

Contents:

Introduction

In modern software development, the use of Dependency Injection is a very important principle. It allows you to build large systems with properly decoupled and testable components. The use of Inversion of Control containers is a popular way of implementing Dependency Injection. If you are unfamiliar with these terms, this article probably isn't for you; I suggest you read Martin Fowler's excellent article about DI and IoC instead :)

In the .NET world there are probably dozens of different IoC containers available. They all serve the same basic need, but there are important differences in the features they offer. One popular IoC container is Unity, created by the Microsoft patterns & practices team.

Just because it's popular, doesn't mean Unity is perfect however. In this multi-part article, I will try to address some issues around classes implementing IDisposable in combination with Unity.

Unity in a Nutshell

Consider that I have a component Foo that relies on some implementation of the IBar interface. The implementation I want my application to use is in the Bar class. We're going to use constructor injection for this:

class Foo
{
    public Foo(IBar bar)
    {
        // ...
    }
}

class Bar : IBar
{
     // ...
}

With Unity, creating a new instance of Foo would look something like this:

var container = new UnityContainer();

// Configure the container to use Bar as the implementation of IBar
// This could be done in a configuration file or similar
container.RegisterType(typeof(IBar), typeof(Bar));

Foo newFoo = container.Resolve<Foo>();

What will happen is that Unity will look at the constructor for Foo and it will try to resolve the IBar dependency. Because I've told the container to use Bar every time someone asks for an IBar, it will first create a new instance of Bar and pass it into the constructor of Foo. Presto!

But what if I create more than one Foo? Do I get two Bar objects as well, or are they both using the same object? In Unity this is controlled by something called a Lifetime Manager. In this case I did not explicitly specify any lifetime manager, which means I will get a new Bar object every time. This is the behavior of the TransientLifetimeManager. Using the ContainerControlledLifetimeManager would return the same Bar object each time. There are several other options.

Disposable Objects

Our example will become a bit more complicated if the Bar class were to implement IDisposable. Now we need to make sure that the Dispose method is called when we're done with the object, but when exactly is that?

In our example above, we get a new Bar object for every Foo, so a naive solution could look something like this:

class Foo : IDisposable
{
    private IBar _bar;

    public Foo(IBar bar)
    {
        _bar = bar;
    }

    public void Dispose()
    {
         IDisposable disposable = _bar as IDisposable;
         if (disposable != null)
             disposable.Dispose();
    }
}

We would just call Dispose on the Foo object when we're done with it, and it in turn will dispose of Bar. However, there is something fundamentally wrong with this approach: Foo did not personally create its private instance of Bar, so it does not know if it's the sole user of that dependency. If the container were to be reconfigured to use the ContainerControlledLifetimeManager, other Foo objects would now have a reference to a disposed object.

The code that called the Resolve<Foo>() also created the Bar object indirectly, but it does not necessarily know what type of lifetime manager is being used either. Basically, neither part of the code should care whether or not the object needs disposing.

Unity and IDisposable

When neither Foo, nor the code creating Foo can be made responsible for disposing Bar, that leaves only one option: the container should take care of it. Unfortunately, in this case Unity is somewhat lacking in features. When using the TransientLifetimeManager, Unity immediately forgets about an object after creating it, so we can forget about it calling Dispose for us. When using the ContainerControlledLifetimeManager, Unity will dispose the object when the container itself is disposed. This is great for Singleton type object, but it may be too restrictive for other scenarios.

An Advanced Use Case

Sometimes you're introducing a dependency that can be shared between multiple objects, but you want its associated resources to be released as soon as they are no longer needed. A few examples:

  • A diagnostic logging component, logging to a file. I want to close the file as soon as I'm done logging stuff from however many objects.
  • Several views binding to a single view model when building a MVVM application. The view model may be triggering continuous information retrieval from a back-end system and we only want to do that once, no matter how many views we have that are showing that data.

Extensibility

Fortunately, Unity is fairly extensible. We can define our own lifetime managers, build strategies and a number of other things that determine the behavior of the container. In part two of the article, we're going to use that extensibility to solve this particular problem.

Continue reading...

Comments (2) -

  • My compliments for your clear and concise writing style (this also holds for part 2 and 3). Idisposible with Unity is obviously a tricky business. For just now, I decided not to use the interface explicitly with Unity.
    Keep up the good work!
  • Sorry for the typo: I meant IDisposable, although a better typo would have been IDispossible...

Pingbacks and trackbacks (1)+

Add comment

Loading