The subject of Dependency Injection (DI) in general, and DI Containers specifically, suffers from horrible terminology that seems to confuse a lot of people. Newcomers to DI often think about DI Containers as a sort of Abstract Factory on steroids. It's not. Nicholas Blumhardt already realized and described this phenomenon a couple of years ago.

The core of the matter is that as developers, we are extremely accustomed to thinking about components and services in terms of queries instead of commands. However, the Hollywood Principle insists that we should embrace a tell, don't ask philosophy. We can apply this principles to DI Containers as well: Don't call the container; it'l call you.

This leads us to what Krzysztof Koźmic calls the three calls pattern. Basically it states that we should only do three things with a DI Container:

  1. Bootstrap the container
  2. Resolve root components
  3. Dispose this container

This is very sound advice and independently of Krzysztof I've been doing something similar for years - so perhaps the pattern label is actually in order here.

However, I think that the pattern deserves a more catchy name, so in the spirit of the Arrange Act Assert (AAA) pattern for unit testing I propose that we name it the Register Resolve Release (RRR) pattern. The names originate with Castle Windsor terminology, where we:

  1. Register components with the container
  2. Resolve root components
  3. Release components from the container

Other containers also support the RRR pattern, but if we were to pick their terminology, it would rather be the Configure GetInstance Dispose (CGD) pattern (or something similar), and that's just not as catchy.

We can rewrite a previous example with Castle Windsor and annotate it with comments to call out where the three container phases occur:

private static void Main(string[] args)
{
    var container = new WindsorContainer();
    container.Kernel.Resolver.AddSubResolver(
        new CollectionResolver(container.Kernel));
 
    // Register
    container.Register(
        Component.For<IParser>()
            .ImplementedBy<WineInformationParser>(),
        Component.For<IParser>()
            .ImplementedBy<HelpParser>(),
        Component.For<IParseService>()
            .ImplementedBy<CoalescingParserSelector>(),
        Component.For<IWineRepository>()
            .ImplementedBy<SqlWineRepository>(),
        Component.For<IMessageWriter>()
            .ImplementedBy<ConsoleMessageWriter>());
 
    // Resolve
    var ps = container.Resolve<IParseService>();
    ps.Parse(args).CreateCommand().Execute();
 
    // Release
    container.Release(ps);
    container.Dispose();
}

Notice that in most cases, explicitly invoking the Release method isn't necessary, but I included it here to make the pattern stand out.

So there it is: the Register Resolve Release pattern.


Comments

Harry Dev #
I agree completely and think the Register Resolve Release (RRR) moniker is very good. You should think about creating a wikipedia or c2 entry for it to promote it ;)
2010-09-29 12:21 UTC
Nice coinage, gets a vote from me.
2010-10-03 21:28 UTC
Arnis L. #
This realization took me few months. It truly is quite hard for newcomers.
2010-10-03 22:42 UTC
You could use a using block, too.
2010-10-07 17:03 UTC
Yes, although the general pattern is a bit more subtle than this. In the example given, the call to the Release method is largely redundant. If we assume that this is the case, a using block disposes the container as well.

However, a using block invokes Dispose, but not Release. Releasing an object graph is conceptually very different from disposing the container. However, in the degenerate case shown here, there's not a lot of difference, but in a server scenario where we use the container to resolve an object graph per request, we resolve and release many object graphs all the time. In such scenarios we only dispose the container when the application itself recycles, and even then, we may never be given notice that this happens.
2010-10-07 21:09 UTC
Great name, I like it. RRR is easy to remember and makes sense to me perfectly. Thanks.
2012-06-09 06:45 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or somewhere else with a permalink. Ping me with the link, and I may respond.

Published

Wednesday, 29 September 2010 11:50:02 UTC

Tags



"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!
Published: Wednesday, 29 September 2010 11:50:02 UTC