Castle Typed Factory Facility reborn

Disclaimer:

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:

public class MessageDispatcher
{
    public void Dispatch(IMessage message)
    {
        var handler = GetHandlerFor(message);
        handler.Handle(message);
        Destroy(handler);
    }
 
    private IMessageHandler GetHandlerFor(IMessage message)
    {
        // how to implement this...
    }
 
    private void Destroy(IMessageHandler handler)
    {
        // ... and this?
    }
}

Solution – take one – the ugly

The easiest option to implement is just to take dependency on the container.

private IKernel container;
private IMessageHandler GetHandlerFor(IMessage message)
{
    return container.Resolve<IMessageHandler>(new { name = message.Name });
}
 
private void Destroy(IMessageHandler handler)
{
    container.ReleaseComponent(handler);
}

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.

public class MessageDispatcher
{
    public void Dispatch(IMessage message)
    {
        var handler = GetHandlerFor(message);
        handler.Handle(message);
        Destroy(handler);
    }
 
    private void Destroy(IMessageHandler handler)
    {
        factory.DestroyHandler(handler);
    }
 
    private IMessageHandlerFactory factory;
 
    private IMessageHandler GetHandlerFor(IMessage message)
    {
        return factory.CreateNewHandler(message.Name);
    }
}
 
public interface IMessageHandlerFactory
{
    IMessageHandler CreateNewHandler(string name);
 
    void DestroyHandler(IMessageHandler handler);
}
 
// in another assembly
public class MessageHandlerFactory : IMessageHandlerFactory
{
    private IKernel container;
    public IMessageHandler CreateNewHandler(string name)
    {
        return container.Resolve<IMessageHandler>(new { name =name });
    }
 
    public void DestroyHandler(IMessageHandler handler)
    {
        container.ReleaseComponent(handler);
    }
}

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?

var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
    // register the handler and all the other components
    Component.For<MessageDispatcher>(), // register the component with dependency on our factory
    Component.For<IMessageHandlerFactory>().AsFactory() //register the factory itself (just the interface)!
    ); // that's it, now get the dispatcher
var dispatcher = container.Resolve<MessageDispatcher>();
//start dispatching...

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 facility to 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.

public class MySelector: ITypedFactoryComponentSelector
{
    public TypedFactoryComponent SelectComponent(MethodInfo method, Type type, object[] arguments)
    {
        string componentName = null;
        if(arguments.Length>0 && arguments[0] is string)
        {
            componentName = arguments[0].ToString();
        }
 
        //let's ignore all other arguments here for simplicity sake
        return new TypedFactoryComponent(componentName, method.ReturnType, null);
    }
}

Little bonus

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.

public interface IGenericFactory
{
    T Create<T>();
}
 
var factory = container.Resolve<IGenericFactory>();
 
var one = factory.Create<ISomeComponent>();
var two = factory.Create<IOtherComponent>();

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.

Technorati Tags:

Posted 12-24-2009 12:12 AM by Krzysztof Koźmic
Filed under:

[Advertisement]

Comments

zihotki wrote re: Castle Typed Factory Facility reborn
on 12-26-2009 5:47 PM

Man, you know, it's just awesome, really!! Thanks for sharing this feature and for you hard work.

Jimmy Bogard wrote re: Castle Typed Factory Facility reborn
on 12-30-2009 8:42 AM

An interesting solution - but I still don't see the advantage.  You've said depending on the container for infrastructure components is a bad thing, but did not elaborate why this is bad.  For 99% of the time, I would agree.  But just putting in a factory to act as a ContainerFacade - I don't see what this is buying you, other than more code to maintain.

Krzysztof Koźmic wrote re: Castle Typed Factory Facility reborn
on 12-31-2009 6:55 AM

@Jimmy,

The advantage of a factory (with the facility or without) is the focus - contract of the factory is explicit as to what you can get out of it, and what you need to pass in.

The advantage of the facility is that you don't need to implement that factory - you only need to specify its contract via the interface.

additional win is that you'd usually specify the interface in your domain assembly, since that's where it'd be used. By doing so you don't need to reference your container (or any other service locator) in your domain assembly which I'm sure you'd agree is rarely a good idea.

Colour Coding wrote Dependency Reversi
on 01-19-2010 4:19 PM

Dependency Reversi

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)