Notice that code shown here is quite new and is subject to change. If you’re reading this and it’s 2010 it’s likely that the code now is slightly different. I may come back and revisit the post if there are any changes, but don’t hold my word on it.
Pulling from the container
General rule of thumb when using IoC containers is – when you’re referencing your container in your components (anywhere outside of your bootstrapping code) you’re doing it wrong. As with all rules there are exceptions, but they are rare. Still, there are cases where you have to pull from the container somehow. What to do then? Let’s use the following artificial example:
Solution – take one – the ugly
The easiest option to implement is just to take dependency on the container.
This option seems the easiest at first. You just call the container directly. However along the way you coupled your component to the container which has whole list of disadvantages and is the wrong thing™ to do.
Solution – take two – the bad
Ok, so if calling the container directly is bad, we can use a layer of abstraction on top of it, right? Like Common Service Locator for example… This way we can swap the container underneath which proves the component has no dependency on the container.
Well, this is certainly a step in the right direction, but it still has a whole range of flaws. First of all – it won’t work in our scenario. Take a closer look at the code above – when we’re resolving the message handler, we’re also passing an argument in. CSL does not support passing parameters. Besides, using CSL just hides the problem instead of solving it – you’re still having a dependency on an infrastructure library in your domain component.
Solution – take three – the good
The least worst way of solving this problem is to introduce dedicated factory which will hide the container from your domain. Doing this manually (provided you want to do it right™) is however a lot of tedious boring work. You have to define an interface for your factory in your domain assembly, then create an implementation in another one, then actually implement all the calls (and not only to resolve, don’t forget about cleaning up after yourself), which as you’ll soon discover is a lot of repetitious code.
Wouldn’t it be good if someone else could do the work for you? – Meet Typed Factory Facility.
Windsor Typed Factory Facility
Typed factory is just the tool for this problem – it’s an automatically created factory, created by container, but your code is unaware of the container. It’s been around since 2005 but due to severe limitations imposed on it, and lack of development in recent years it hasn’t been widely used.
However it’s been recently retuned, with new capabilities and old limitations have been removed. It’s considerably more usable now, hence the word reborn in the title on this post. Let’s get to the code, shall we?
we register the facility with the container, than we register all the components the usual way. When we want to use an interface as a factory, we register it without any implementation (if you pass an implementation it will be ignored) and then call the AsFactory() extension method, and we’re all set.
Now the kernel will implement the factory for you based on few conventions
- all the void methods are assumed to be used to release components passed as arguments
- all the non-void methods are assumed to be used to resolve components from the container
- If the factory implements IDisposable, the call to dispose will release all the transient components that were resolved via the factory.
Now, how does the factory know which service to request from the container? By default:
- Method’s return type is used to request the component by type
- If the method on the factory interface is called GetSOMETHING, the component called SOMETHING will be requested by name
- All the arguments passed to the method, will be forwarded to the container with names of the method’s parameters.
This however, is just the default behavior – you can easily change it, by implementing ITypedFactoryComponentSelector and registering it with the container. Then your implementation will be picked, and used to bind factory methods and their arguments to information used by the resolve appropriate components.
Custom ITypedFactoryComponentSelector – example
For example, let’s say you don’t like the GetSOMETHING convention, and decided that if the first argument of typed factory method is a string, it should be bound to component’s name instead.
One thing about this facility that blew my mind, is that the factory is not limited to resolving a single type – with literally no effort you can use it to build a generic service locator.
The code is in the trunk. It may still contain bugs and not support all scenarios, so approach with caution, and as always – any feedback is appreciated.