How I use Inversion of Control containers – pulling from the container

As I expected my previous post prompted a few questions regarding the Three Container Calls pattern I outlined. Major one of them is how to handle the following scenario:

Container_pulling

We create our container, install all the components in it.  Moments later we resolve the root component, container goes and creates its entire tree of dependencies for us, does all the configuration and other bookkeeping, injects all the dependencies and gives us back the new fresh ready to use objects graph that we then use to start off the application.

More often than not, this will not be enough though. At some point later in the lifecycle of the application, a user comes in and wants something from the application. Lets say the user clicks a button saying “Open a file” and at this point a “OpenFile” view should be loaded along with all of its dependencies and presented to the user. But wait – it gets worse – Because now if a user selects a .txt file a “DisplayText” view should be loaded, but when a .png file gets selected, we should load a “DisplayImage” view.

Generalizing – how to handle situations where you need to request some dependencies unavailable at registration or root resolution time, potentially passing some parameters to the component to be resolved, or some contextual information affecting which component will be resolved (or both).

Factory alive and kicking

The way to tackle this is to use a very old design patterns (from the original GOF patterns book) called Abstract factory and Factory method.

Nitpickers' corners – as I know I will be called out by some purists that what I’m describing here is not purely this or that pattern according to this or that definition  – I don’t care, so don’t bother. What’s important is the concept.

It gives us exactly what we need – provides us with some components on demand, allowing us to pass some inputs in, and on the same time encapsulating and abstracting how the object is constructed. The encapsulating part means that I totally don’t need to care about how, and where the components get created – it’s completely offloaded to the container. The abstracting part means that I can still adhere to the Matrix Principle – the spoon container does not exist.

How does this work?

Using Castle Windsor, this is very simple – all you have to do is to declare the factory interface, and Windsor itself will provide the implementation. It is very important. Your interface lives in your domain assembly, and knows nothing about Windsor. The implementation is a detail, which depends on the abstraction you provided, not the other way around. This also means that most of the time all of the work you have to do is simply declaring the interface, and leave all the heavy lifting to Windsor, which has some pretty smart defaults that it will use to figure this stuff out by itself. For non-standard cases, like deciding which component to load based on the extension of the file provided, you can easily extend/customize the way factory works by using custom selector. With well thought out naming convention, customizing Windsor to support this scenario is literally one line of meaningful code.

In addition to that (although I prefer the interface-driven approach) Windsor (upcoming version 2.5), and some other containers, like Autofac (which first implemented the concept), and StructureMap (don’t really know about Ninject, perhaps someone can clarify this in the comments) support delegate based factories, where just the fact of having a dependency on Func<IFoo> is enough for the container to figure out that it should inject for that dependency a delegate that when invoked will call back to the container to resolve the IFoo service. The container will even implement the delegate for you, and it also obviously means that the code you have has no idea (nor does it care) that the actual dependency was created by a container.

 

This is the beauty of this approach – it has all the pros and none of the cons of Service Locator, and shift towards supporting it was one of the major changes in the .NET IoC backyard in the last couple of months, so if you are still using Service Locator you’re doing it wrong.


Posted 06-22-2010 1:52 PM by Krzysztof Koźmic
Filed under: ,

[Advertisement]

Comments

Jason Meckley wrote re: How I use Inversion of Control containers – pulling from the container
on 06-22-2010 9:10 AM

thanks for the insight. I had no idea this gem existed!

Arild Fines wrote re: How I use Inversion of Control containers – pulling from the container
on 06-22-2010 10:26 AM

Thanks, that's pretty much what I'm doing now (although manually injecting the Funcs; wasn't aware that this is built into StructureMap).

tomas wrote re: How I use Inversion of Control containers – pulling from the container
on 06-23-2010 7:50 AM

It would be really nice to see what this three-call approach would look like in Ninject, where injection is normally handled through attributes, which in turn require a reference to the Ninject assembly in every project (and it clutters up my code, too...).

Do you have any great ideas?

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)