Sunday, January 10, 2010

10 Advanced Windsor Tricks – 1. Registering Delegates

Here’s part one of (at least) 10 Advanced Windsor Tricks.

Did you know that you can register delegates in Windsor? Here I’m just registering a Func<String> that returns “Hello World”

var container = new WindsorContainer()
    .Register(
        Component.For<Func<string>>().Instance(() => "Hello World")
    );

var sayHello = container.Resolve<Func<string>>();
Console.WriteLine(sayHello());

This will print out ‘Hello World’ on the console.

This has some pretty cool implications. For example, say you want to resolve different named instances of the same component at runtime. Without this trick you would have to reference the container itself, which is an IoC anti-pattern of epic proportions. Instead, just register a delegate that takes a string and returns your service type then supply container.Resolve<MyServiceType> as it’s instance. Confused? Here’s an example:

First two classes: Do and BigDo (smirk:)

public class Do
{
    public virtual void SayHello()
    {
        Console.WriteLine("Hello from Do");
    }
}

public class BigDo : Do
{
    public override void SayHello()
    {
        Console.WriteLine("Hello from BigDo");
    }
}

BigDo inherits Do and they both implement ‘SayHello’. Now here’s a class that depends on something of type ‘Do’, but doesn’t know which named ‘Do’ it wants until runtime:

public class UseDo
{
    private readonly Func<String, Do> doFactory;

    public UseDo(Func<String, Do> doFactory)
    {
        this.doFactory = doFactory;
    }

    public Do GetDo(string name)
    {
        return doFactory(name);
    }
}

It takes a delegate dependency Func<String, Do> which acts as a ‘Do Factory’. At runtime a client can call ‘GetDo’ to return the named ‘Do’ it wants. The container registration is very simple:

var container = new WindsorContainer();
container
    .Register(
        Component.For<Do>().Named("do1"),
        Component.For<Do>().ImplementedBy<BigDo>().Named("do2"),
        Component.For<Func<String,Do>>().Instance(container.Resolve<Do>),
        Component.For<UseDo>()
        );

First we register the two different implementations of ‘Do’ and give them both names. Next we register the factory delegate. We can simply pass the method cotainer.Resolve<Do> as the delegate instance because one of Resolve<Do>’s overrides takes a string argument and returns Do. Finally we register the client class ‘UseDo’.

Now we can call UseDo.GetDo and return different named versions of Do:

var useDo = container.Resolve<UseDo>();
var do1 = useDo.GetDo("do1");
var do2 = useDo.GetDo("do2");

do1.SayHello();
do2.SayHello();

Which prints out the following on the console:

Hello from Do
Hello from BigDo

You could use this same trick to resolve multiple named component configurations which I’ve seen a lot of recently (yes, you know who you are). One step on from here would be to have Func<T> automatically wired up to container.Resolve<T>() and Func<String, T> to container.Resolve<T>(name) a la Autofac. Hmm…..

1 comment:

DavidS said...

Hi Mike,

You've said:

"For example, say you want to resolve different named instances of the same component at runtime. Without this trick you would have to reference the container itself, which is an IoC anti-pattern of epic proportions. Instead, just register a delegate that takes a string and returns your service type then supply container.Resolve as it’s instance"

In your example, which is of course simplistic, I can see how this is done. However, say you needed to resolve the implementation deep down in the object graph, how would you then use this technique?

I hope that my question is clear.