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:

   1: var container = BootstrapContainer();
   2:  
   3: var finder = container.Resolve<IDuplicateFinder>();
   4: var processor = container.Resolve<IArgumentsParser>();
   5: Execute( args, processor, finder );
   6:  
   7: 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:

   1: private IWindsorContainer BootstrapContainer()
   2: {
   3:     return new WindsorContainer()
   4:         .Install( FromAssembly.This() );
   5: }

 

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:

   1: public class ArgumentInterpretersInstaller : IWindsorInstaller
   2: {
   3:     public void Install(IWindsorContainer container, IConfigurationStore store)
   4:     {
   5:         container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel));
   6:         container.Register(
   7:             Component.For<IArgumentsParser>()
   8:                 .ImplementedBy<ArgumentsParser>().LifeStyle.Transient,
   9:             Component.For<IParseHelper>().ImplementedBy<ParseHelper>(),
  10:             AllTypes.FromAssemblyContaining<IArgumentInterpreter>()
  11:                 .BasedOn<IArgumentInterpreter>()
  12:                 .WithService.Base());
  13:     }
  14: }

 

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?


Posted 06-20-2010 2:48 PM by Krzysztof Koźmic
Filed under:

[Advertisement]

Comments

Martin wrote re: How I use Inversion of Control containers
on 06-20-2010 4:17 PM

Thanks for this great article. This is exactly the piece of information I was always missing: how to avoid the Service Locator pattern and how to prevent referencing the container everywhere. I guess, I'm now ready to use an IOC container.

Krzysztof Koźmic wrote re: How I use Inversion of Control containers
on 06-20-2010 6:05 PM

@Martin,

cool - glad you found the information useful. I'm gonna deepen the topic of avoiding SL in the next post.

Leon Breedt wrote re: How I use Inversion of Control containers
on 06-20-2010 7:05 PM

Yep, this is how I use Autofac as well.

I think the IoC containers should do a better job of guiding people away from using it as a Service Locator, virtually every project I've worked on that has used "IoC" does this.

IoC component registration should be something you do pretty much once and then forget about because everything that consumes services just gets the reference it needs.

Ollie Riches wrote re: How I use Inversion of Control containers
on 06-21-2010 5:00 AM

In a request based application (lets say the web) would you recommend creating a child container per request and disposing of that upon completion?

Sanjeev Agarwal wrote Daily tech links for .net and related technologies - June 21-23, 2010
on 06-21-2010 6:39 AM

Daily tech links for .net and related technologies - June 21-23, 2010 Web Development ASP.NET Internals

Krzysztof Koźmic wrote re: How I use Inversion of Control containers
on 06-21-2010 7:19 AM

@Ollie

That depends on the particular container you're using.

If you want to use this just to limit the lifetime scope of the components, I would not, if I was using Windsor - PerWebRequest lifestyle is the way to go here.

On the other hand, Autofac for example I think is doing just this itself.

Arild Fines wrote re: How I use Inversion of Control containers
on 06-21-2010 8:39 AM

But what are the patterns one should prefer if one wants to use the container to resolve components in a parameterized fashion? It's hard to avoid touching the container in that case.

For example, if you want to instantiate a view/viewmodel tuple for a, say, "Edit Customer Information" dialog. In that case, you want to parameterize on the customer, but let the container resolve everything else.

James Curran wrote re: How I use Inversion of Control containers
on 06-21-2010 1:39 PM

In th efirst line after the Installer code sample, you say "...and by leveraging Installers you end up writing less code, as no Windsor will autodiscover them..."

I assume you meant, "as NOW Windsor will autodiscover them"

Normally, I wouldn't bug you over a minor typo, but the error changes the meaning of the sentence.

Richard J Foster wrote re: How I use Inversion of Control containers
on 06-21-2010 2:29 PM

While I agree that in principle assemblies should not have any reference to the container, this isn't always as easy as might be desired. In the scenario where a specific assembly represents an optional "plug in" component requiring its own (similarly optional) Installer, what mechanism would you use?

(While it is certainly possible to add two assemblies for each plug-in, one containing the optional functionality, one containing the IoC Installer, that option feels wasteful to me. I tend to place the add-in's Installer in the same assembly, which naturally requires a reference to the IoC container. Is there a better mechanism?)

dob wrote re: How I use Inversion of Control containers
on 06-21-2010 4:01 PM

does this method work for WCF services

Krzysztof Koźmic wrote re: How I use Inversion of Control containers
on 06-21-2010 5:30 PM

@Richard J Foster

"I tend not to reference the container in the application".

That means I logically DON"T do it unless I'm extending the container itself. I physically don't do it when I can live without it.

The scenario you're describing is one where I would likely reference Windsor in the container but not use it explicitly outside of the Installer(s)

da5id wrote re: How I use Inversion of Control containers
on 06-22-2010 7:41 AM

Hi,

thanks for the articel. Just one question:

From my point of view, not everything can be contained as a service in that container - especially classes that are created on the fly while working on specific tasks that also needs some services from the container .  How do you handle these scenarios? Do you get the service directly from the container? Or do you wire each and every class that needs a reference to the container?

cheers

da5id

John wrote re: How I use Inversion of Control containers
on 06-22-2010 11:33 AM

Thanks for writing this great article.  Would it be possible to provide a sample/demo application to better demonstrate this?  I still have a difficult time understanding how to register components when an interface has multiple concrete classes that need to be instantiated depending on the situation.  

Krzysztof Koźmic wrote re: How I use Inversion of Control containers
on 06-23-2010 8:14 AM

@John,

does my following post answer your questions?

You may also want to take a look at Dynamic Parameters and HandlerSelectors in Windsor

StarTrekRedneck wrote re: How I use Inversion of Control containers
on 06-27-2010 10:32 PM

Great post. One question. In the case of an ASP.Net MVC (2) app, do you still have the container in a separate project, and if so, what type of dll is it (another web app, console, library, etc.)?

thanks a heap and I really liked the subsequent post as well.

Krzysztof Koźmic wrote re: How I use Inversion of Control containers
on 06-30-2010 6:36 AM

@StarTrekRedneck  

I don't usually work in web, but I tend to keep the container in my root level - entry point project, so yes - I keep it in the main web project.

Sant wrote re: How I use Inversion of Control containers
on 09-08-2010 10:13 PM

Thanks a lot for this crisp implementation. I am new to this IoC stuff so forgive me for ignorance.

How do you implement this in the case where an application consists of  multiple assemblies.

a) WPF App Project

b) SomeLibrary1.dll

b) SomeLibrary2.dll

and so on. Each of these libraries have interfaces and their implementations (sometimes multiple implementations)

Also in SomeLibrary2.dll, I need to get handle to the IWindsorContainer because I need to resolve ALL implementations of a particular interface. Something like this:

Container.ResolveAll<IMyInterface<T>>();

Appreciate your help.

Sant wrote re: How I use Inversion of Control containers
on 09-08-2010 11:52 PM

just to continue from above:

Shouldn't I have to add references to ALL assemblies to IoC project (that contains installers)?

Krzysztof Koźmic wrote re: How I use Inversion of Control containers
on 09-09-2010 9:27 AM

@Sant  

1. See the next post

2. You don't need to have compile time references to all assemblies in the root project.

You can use conventions and register types based on assebly name, location, key or whatever else.

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)