How I use Inversion of Control containers

Quite regularly I get asked by people how they should use IoC container in their application. I don’t think I can answer this question once and universally because every application is different, every application has different needs and every application has different opportunities for leveraging an Inversion of Control container.

However there are some general rules and patterns that I use and I thought I will blog about this instead.

While I use a concrete example of Castle Windsor, the discussion here is universal.It applies to all containers.

Inversion of Control means container does not exist

Container_does_not_exist

Basic difference between an Inversion of Control framework and any other kind of framework is that the control gets inverted. Your application does not call to the framework. Instead the framework is aware of your application and it goes and does its stuff with your application’s objects.

Since Inversion of Control Containers are Inversion of Control frameworks that paradigm applies to them as well. They control objects in your application. They instantiate them, manage their lifecycle, invoke methods on them, modify them, configure them, decorate them, do all sorts of stuff with them. The main point here is – the application is completely unaware of that. I feel tempted to put another Matrix analogy here, but hopefully you get the point without it.

The most visible manifestation of this fact, which clearly illustrates the lack of any knowledge about the container is that I tend not to reference the container in the application at all. The only place where the reference to the container does appear is the root project which only runs the application. It however contains no application logic and serves merely as application entry point and container bootstrapper.

Not referencing the container at all serves a few purposes. Most importantly it helps to enforce good OOP design, and blocks the temptation to take shortcuts and use the container as Service Locator.

Three calls pattern of usage

Now, probably the most interesting part is this simple bootstrapper. How do I interact with the container?

I tend to use pattern of three calls to the container. Yes you heard it right – I only call the container is three places in the entire application* (conditions apply, but I’ll discuss this below in just a moment).

My entire interaction with the container usually looks like this:

var container = BootstrapContainer();

finder = container.Resolve<IDuplicateFinder>();
var processor = container.Resolve<IArgumentsParser>();
Execute( args, processor, finder );

container.Dispose();

The three steps are:

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

Let’s go over them in turn:

One Install to rule them all…

Bootstrapping is incredibly simple:

private IWindsorContainer BootstrapContainer()
{
    return new WindsorContainer()
                  .Install( FromAssembly.This() );
}

The most important rule here (which is important in Windsor, but good to follow with other containers that enable this)  is – to call Install just once and register and configure all the components during this single call. Also important stuff is to use the Install method and Installers to encapsulate and partition registration and configuration logic. Most other containers have that capability as well. Autofac and Ninject call it modules, StructureMap calls it registries.

As you can see on the screenshot above I usually have a dedicated folder called Installers in my bootstrap assembly where I keep all my installers. I tend to partition the installers so that each one of them installs some cohesive and small set of services. So I might have ViewModelsInstaller, Controllers Installer, BackgroundServicesInstaller, LoggingInstaller etc. Each installer is simple and most of them look similar to this:

public class ArgumentInterpretersInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel));
        container.Register(
            Component.For<IArgumentsParser>()
                .ImplementedBy<ArgumentsParser>().LifeStyle.Transient,
            Component.For<IParseHelper>().ImplementedBy<ParseHelper>(),
            AllTypes.FromAssemblyContaining<IArgumentInterpreter>()
                 .BasedOn<IArgumentInterpreter>()
                 .WithService.Base());
    }
}

This partitioning helps keep things tidy, and by leveraging Installers you end up writing less code, as now Windsor will autodiscover them and register in just a single call to FromAssembly.This(). Also another noteworthy fact about this, is that you leverage Inversion of Control principle to configure the container itself. Instead of passing the container around, which should always raise a read flag, you’re telling Windsor – configure yourself. Nice and tidy.

Another important thing to notice, is that I tend to leverage convention based registration, rather than registering all the components one by one. This greatly cuts down the size of your registration code. It takes the burden of registering each newly added components manually off of your shoulders. It also enforces consistency in your code, because if you’re not consistent your components won’t get registered.

* yes – I do interact with the container in the installers, so I clearly break the three calls rule, right? No – I interact with the container in objects that extend, or modify the container itself – in this case it’s obviously not a bad thing.

…and in one Resolve bind them

Similar to unit tests principle – one logical assert per tests, I follow the rule of allowing explicit call to resolve in just one place in the entire application. Usually this will be just one call, that pulls the root component (Controller in MVC application, Shell in WPF application, or whatever the root object in your app is). In the example above I have two root objects so I have two calls to Resolve. That’s usually OK. However if you have more than three, you might want to take a closer look at reasons for that, as it’s quite unlikely you really need this.

The important thing is to have the Resolve calls in just this one single place and nowhere else in your application. Why that’s important? To fully leverage container’s potential, instead of telling it at every step what it should do. Let it spread its wings.

Clean up

It is important to let the container clean up after itself, when its done doing its job. In this case I can not only say that this is something I do. You also always should dispose your container at the end of your application. Always, no exceptions. This will let the container to shutdown gracefully, decommission all the components, give them chance to clean up after themselves, and free all the resources they may occupy.

 

What about you? How do you use your container?

Comments

Omer Mor says:

Thanks for sharing.
Your usage looks much like how I was using my container, when I only used it to create singletons.
However since I started to create transient objects as well I found myself resolving in more places.
Can you address the issue of transients please?

@Omer – I will, that’s the next post. I actually did show this already in previous posts, I just didn’t call that "how I resolve transient components from the container."

@Omer – I will, that’s the next post.

John Simons says:

Awesome post, thanks mate.
Looking forward to the next post about dealing with transients 🙂

Thanks for the really interesting post.

I am keen to see how you handle wiring up views to [presenters|controllers|view models]. I’ve commonly resorted to exposing a restricted interface of the container (ViewFactory) so I can use the container to resolve views, but this has always felt dirty to me (and breaks your rule of only one call to Resolve). Any suggestions?

Phil Hoy says:

How do you deal with reusing installers across solutions?

@Phil,

Installers are pretty focused. Why would I want to reuse them?
Can you explain what you mean?

Eli Thompson says:

Would it also be the case in a WebForms website that I’d need to resolve the root components on the ASPX pages because each of those pages is an entry point of the application?

I think this is good general advice, you should be clearer though that assembly references aren’t a problem per se, but more of a rule of thumb when using certain containers.

For example, many IoC libraries (Ninject, MEF, Unity) use attributes for configuration. These require assembly references, but regardless of your feelings about attributes, they don’t make the result any less "best practice" IoC.

Nit-picking, I know. Enjoyed the article! 🙂

Mark Seemann says:

@Nicholas Blumhardt: I have to take sides with Krzysztof here. If you have an assembly reference because you need to apply attributes, you make it much easier to make further mistakes. Experienced developers like you are not likely to fall victim to that, but (DI) beginnners might.

It also becomes much harder (perhaps even impossible) to write unit tests that safeguards against incorrect coupling (consider this example: blogs.msdn.com/…/…shouldnotreferenceunity.aspx).

Phil Hoy says:

You might want to share an installer if a component is used in a couple of apps. say a windows app and a web app.

@Phil

Than it’s not an issue. You’re free to reuse the installers anyway you like. They dont have to be tied to any particular host in anyway

Phil Hoy says:

Sorry I was not clear.

Where would you put the installer classes for a component from an assembly when the assembly is used in two different solutions.

Would you copy the installer class and put in in the top level projects in each solutions or would you put it in with the assembly with the installed components?

Yeah, I usually copy the code. It’s not worth reusing this on binary level, since you’re likely to do small tweaks, specific to the project at hand.

Morten Jacobsen says:

Hi,

Could you comment on how you would wire up views and presenters (WinForms MVP) with this approach?

Regards,
Morten

@Morten Jacobsen

Just like any other component? I can’t see anything special about them. Can you elaborate what exactly are you having doubts about?

Morten Jacobsen says:

@Krzystof

Maybe I’m wrong, I was just thinking that the circular nature would screw something up (i.e. the view has to know the presenter, and the presenter has to know the view)? Naturally, both constructors can’t accept the dependency (i.e. SomeView(SomePresenter presenter) and SomePresenter(SomeView view)), so how do you overcome this? Do you have a property that windsor will inject e.g. the presenter into or do you use another technique..

This may seem like a stupid question, but I’m still new to Windsor, so I’m still in the learning process..

@Morten Jacobsen

in classing MVP view has no knowledge of the presenter.

Speaking more broadly, Windsor will not do any magic. You need to break dependency cycles yourself, usually one object sets itself to a property of another in this kinds of situations.