Owned without Owned<> – Part 1

Our neverending quest to make our code neater and tidier continues.

“Given a screen in our application, when the screen closes, make sure everything has been disposed.”

Seems reasonable.

When using a DI container such as Autofac, it seems like a good idea to make the most of its powerful features. If we create the screen is its own child container / lifetime scope, then disposing of that child container disposes the screen and all other objects that it resolved (or that they resolved and so on).

This works very nicely and viewing the app under the memory profiler magnifying glass confirms that everything is being cleared away nicely.

Owned<T>

The syntax for creating the Child Container in AutoFac is by injecting the object you want wrapped (for example the screen) inside an Owned<T>. For more details, see the AutoFac Documentation or Nicholas Blumhardt’s “An Autofac Lifetime Primer”.

Whilst Owned is without doubt powerful and useful, it does has the slight drawback that the fact that an object is Owned can leak out of your component.

So for example, let’s say you are using a strategy pattern to create different Screens, like this:


// Our example Strategies look like this:
public interface IStrategy
{
     IScreen GetScreen();
}

// Here's a strategy that returns Red Screens
public class RedStrategy : IStrategy
{
    private Func<RedScreen> _redScreenFactory;

    // Inject our factory
    public RedStrategy(Func<RedScreen> redScreenFactory)
    {
        _redScreenFactory = redScreenFactory;
    }

    public IScreen GetScreen()
    {
        return _redScreenFactory();
    }
}

You can imagine having several different types of strategies returning, say, Blue and Green screens.

Anyway, let’s say that Red Screens create lots of children and are particularly prone to leaking memory. It would be nice to wrap them in an Owned.

However, what does our strategy return to the consumer?


public class RedStrategy : IStrategy
{
    // Our factory now creates Owned<RedScreen>
    private Func<Owned<RedScreen>> _redScreenFactory;

    // Inject our factory
    public RedStrategy(Func<Owned<RedScreen>> redScreenFactory)
    {
        _redScreenFactory = redScreenFactory;
    }

    public IScreen GetScreen()
    {
        var ownedRedScreen = _redScreenFactory();
        return // ...?
    }
}

If we return ownedRedScreen.Value then we are losing the reference to the child container. This means that we can’t dispose it and clean up all of the contents.

On the other hand, if we change the IStrategy interface to this:

Owned<IScreen> GetScreen()

…then we are forcing all IStrategy implementations to wrap their IScreens in a child container. We are also leaking the fact that they are Owned the consumer and it must now handle Owned<IScreen>.

(This is not to even mention that Owned<RedScreen> can’t be cast to Owned<IScreen> either).

I’ll explain a couple of solutions we came up with – one neat, and one very neat (imho of course :-))

Advertisements