How to avoid (unnecessarily) touching the container

…or “How to resolve stuff all over the place” – two appropriate titles for a blog post that shows the solution to a problem you will eventually run into when using an IoC container… if not in your first application, then maybe in the next…

What’s the problem?

Not all applications lend themselves equally well to leveraging an IoC container for resolving stuff. Generally, applications that follow some kind of request-response pattern are easy to adapt to use the container to build objects that handle requests: Just resolve some kind of handler that handles each request.

E.g.: It is trivial to make Castle Windsor resolve/release controllers in an ASP.NET MVC application by implementing a CastleWindsorControllerFactory.

There are applications however, that do not follow this kind of pattern – or at least not as clearly. Take for instance a typical Windows Forms desktop application that looks like this:

An attempt to use the container could look like this:

But then one problem remains: How can we make the Windows Forms application use our beloved Windsor Container without resolving the entire world at this point?

E.g. if MainForm at some point needs to show a SubForm, then how do we do that without doing a new SubForm() inside of MainForm, thus tying MainForm directly to the concrete SubForm? (and worse: ruining our ability to unit test MainForm…?)

Let’s try using a service locator

In order to avoid new’ing up SubForm, we could use a service locator to provide the form to us. Consider this button handler:

That solves the problem, right? Wrong! I mean, now SubForm can have dependencies injected and stuff, but MainForm is tied to a class called ServiceLocator with a static generic method that creates stuff.

That’s pretty hard to unit test, and in the long run this will just prove to be a serious PITA.

How to fix the problem

If we wanted to fix the problem with MainForm and SubForm, we could do it by passing a ISubFormFactory to MainForm like so:

thus allowing MainForm to instantiate SubForms at will without depending directly on the container. Now on to implement ISubFormFactory:

Now, why is that implementation uncool? There are several reasons, and two of them are: 1) I’m tying myself to a Windsor container somewhere in a static variable in my app, and 2) The implementation is stupid and boilerplate – I need to write one of these every time I need to show a new form… Uncool!

Enter TypedFactoryFacility

Windsor comes with a bunch of facilities in the box, and one of them fits this gap nicely: <a href="http://stw.castleproject.org/Windsor.Typed-Factory-Facility.ashx">TypedFactoryFacility</a>.

If TypedFactoryFacility had a tagline it would be either “The missing link!” or “Gimme another chance!” or something like that.

Put shortly, TypedFactoryFacility gives the container the ability to dynamically implement the ISubFormFactory interface from above, thus allowing my code to pull stuff from the container without even knowing it! \o/

In order to do that, I need to start out by registering the facility;

and then I need to register my factory service like so:

Now the container will delegate the call to CreateSubForm() to container.Resolve<SubForm>(), based on the return type of the factory method – nifty!

When working with Windsor, it is very important that everything that has a transient lifestyle gets properly released! – the facility has this capability as well, just implement a method with the following signature on the factory: void Release(SubForm subForm).

Now our MainForm’s event handler can look like this:

allowing Windsor to properly take care of decommission concerns, thus properly disposing IDisposables and more.

I hope this post gave an understandable introduction to TypedFactoryFacility. To help some more, I have created a simple Windows Forms application on GitHub that shows how a simple Windows Forms application can implement a simple MVC pattern using Castle Windsor and TypedFactoryFacility.

Comments, questions and suggestions are appreciated 🙂