21 Dec
2008

The Resolvable

Category:General PostTag: :

I wrote a post last week about a memory leak i had introduced in my code due to not properly releasing resolved components through the Windsor IoC container. I wanted to try to make sure that i’d never make that mistake again and this is the approach i came up with.

If you’re using an IOC container it’s important to not use it all over the place. You basically use it in as few places as possible to resolve a component and you let the container sort out all of the dependencies. So in the few places where you use the container directly, you need to resolve the component, and in case of transient components you also need to release them through the container. Releasing it is very easy to forget, so i wanted something that would guarantee that the component would be properly released. Enter the Resolvable class:

    public class Resolvable<T> : Disposable

    {

        private readonly T instance;

 

        public Resolvable() : this(null) {}

 

        public Resolvable(object argumentsAsAnonymousType)

        {

            if (argumentsAsAnonymousType == null)

            {

                instance = IoC.Container.Resolve<T>();

            }

            else

            {

                instance = IoC.Container.Resolve<T>(argumentsAsAnonymousType);

            }

        }

 

        public T Instance

        {

            get { return instance; }

        }

 

        protected override void DisposeManagedResources()

        {

            IoC.Container.Release(instance);

        }

    }

The Resolvable class inherits from my Disposable class, so the Disposable pattern is correctly implemented.

From now on, instead of calling the container directly, i just instantiate a new Resolvable in a using block. Let’s try it out.

I’m reusing my test component with a dependency from one of the previous posts:

    public interface IDependency : IDisposable

    {

        bool Disposed { get; set; }

    }

 

    public class MyDependency : IDependency

    {

        public bool Disposed { get; set; }

 

        public void Dispose()

        {

            Disposed = true;

        }

    }

 

    public interface IController : IDisposable

    {

        bool Disposed { get; set; }

        IDependency Dependency { get; }

    }

 

    public class Controller : IController

    {

        public IDependency Dependency { get; private set; }

 

        public Controller(IDependency myDependency)

        {

            Dependency = myDependency;

        }

 

        public void Dispose()

        {

            Dependency.Dispose();

            Disposed = true;

        }

 

        public bool Disposed { get; set; }

    }

Now, instead of resolving an IController directly through the container and having to dispose of it, i just do this:

        [Test]

        public void ResolvableInstanceIsProperlyReleasedAfterDisposal()

        {

            IoC.Container.Register(Component.For<IController>().ImplementedBy<Controller>().LifeStyle.Transient);

            IoC.Container.Register(Component.For<IDependency>().ImplementedBy<MyDependency>().LifeStyle.Transient);

 

            IController controller;

            IDependency dependency;

 

            using (var resolvable = new Resolvable<IController>())

            {

                controller = resolvable.Instance;

                dependency = controller.Dependency;

            }

 

            Assert.IsTrue(controller.Disposed);

            Assert.IsTrue(dependency.Disposed);

            Assert.IsFalse(IoC.Container.Kernel.ReleasePolicy.HasTrack(controller));

            Assert.IsFalse(IoC.Container.Kernel.ReleasePolicy.HasTrack(dependency));

        }

The container doesn’t hold the reference to the instance, and both the instance and its dependency is properly disposed.

8 thoughts on “The Resolvable

  1. Pretty Cool Davy. I was hanging out with Glenn Block at Kaizen and he wrote something very similar which he called IResolver. He was solving a different problem in that you dont always have the luxury of, or want, a container reference, but the pattern is exactly the same. I really like how you have used it to solve the disposable problem you have been posting about.

  2. You may want to seriously consider looking at Autofac, an IoC container which handles disposals. It does this by tracking much the same way you are above but without all the custom code.

  3. Autofac is pretty cool, though changing Containers is usually not an option once development is full swing.

    The nested container approach doesn’t bother me actually, it has some good benefits. I think MEF is going to do the same. In fact, I think the AutoFac guy is on the MEF team?

Comments are closed.