The Resolvable
Posted by Davy Brion on December 21st, 2008
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.
December 22nd, 2008 at 3:50 pm
[...] The Resolvable (Davy Brion) [...]