Skip to content

When dependency injection meets IDisposable

by Alex Peck on June 21st, 2009

What follows is a solution which should really have been obvious to me the first time I faced the problem: how do you decouple logic and instantiation of collaborating objects when faced with a class you need to instantiate inline, such as an IDisposable class? Consider this:

public class NiceClass
{
    private DependentClass injectedDependency;
 
    public NiceClass(DependentClass injectedDependency)
    {
        this.injectedDependency = injectedDependency;
    }
 
    public void CoupledMethod()
    {
        using (IFace c = new Face(injectedDependency))
        {
            // do something with c
        }
    }
}

We can see that injectedDependency is not coupled, but what about the local instance of Face in CoupledMethod? To decouple it use a delegate to return the IFace instance instead of calling new directly. If the coupling had been to a concrete type (Face), we could refactor to an abstract type (IFace) or proxy first.

public class NiceClass
{
    private DependentClass injectedDependency;
    private Func<DependentClass, IFace> faceFactoryMethod;
 
    public NiceClass(
        DependentClass injectedDependency, 
        Func<DependentClass, IFace> faceFactoryMethod)
    {
        this.injectedDependency = injectedDependency;
        this.faceFactoryMethod = faceFactoryMethod;
    }
 
    public void CoupledMethod()
    {
        using (IFace c = this.faceFactoryMethod(injectedDependency))
        {
            // do something with c
        }
    }
}

This is an additional three lines of code, which arguably makes the control flow harder to read statically. It does, however, improve testability. I think of this as equivalent to the classic tradeoff between abstract and concrete parameters.

Instantiating NiceClass is not too arduous either with a lambda expression (although it is still a little verbose).

NiceClass nice = new NiceClass(dependency, d => new Face(d));
No comments yet

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS