One of the great features of Castle Windsor container is the ability to use typed-factories. Basically typed factories act like object factories that use container to create the objects for you, but additionally they let your application decouple from the container implementation.

This is achieved by only defining an interface (or delegate) for you factory and container will do the rest for you. In the Silverlight example application there is a factory that creates Customer objects for us, the inteface is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface IModelFactory
{
/// <summary>
/// Creates a new model
/// </summary>
TModel CreateModel<TModel>() where TModel : IModel;

/// <summary>
/// Releases the instance to get
/// garbage collected
/// </summary>
void FreeUpModel(object oldModel);
}

There are two methods on the interface, one creates an instance of the provided model type and the other frees up the model and make it available to the garbage collection. The important thing to notice here is that there is no implementation of this interface which will be done for us by the container. To use this, you need to register the typed factory facility and add your interface as a factory type:

1
2
3
4
5
6
7
8
public class ServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IModelFactory>().AsFactory());
}
}

If you take a closer look at the resolve overloads on the container, it comes with both generic and non-generic overloads, so we should basically be able to have a version of the typed-factory interface that accepts a type and creates the object for us. Going down that road we’d have this interface:

1
2
3
4
5
6
public interface IModelFactory
{
IModel CreateModel(Type modelType);

void FreeUpModel(object oldModel);
}

Except that this won’t work and you’ll end up with a runtime exception. The reason is Windsor tries not to go ahead and make assumptions for you on the type of the service so you’ll need to specify the service type explicitly. This is done by using other overload of AsFactory extension method where it accepts a TypedFactoryConfiguration which we’ll use to let Windsor know how to resolve create the requested object. In this example, since the service type of the object is the first parameter of the CreateModel method, we just select the first argument as type and we’re done:

1
2
3
4
5
6
7
public class FirstArgumentIsServiceSelector : DefaultTypedFactoryComponentSelector
{
protected override Type GetComponentType(MethodInfo method, object[] arguments)
{
return (Type)arguments.Single();
}
}

And the registration code would be:

1
2
3
4
5
6
7
8
9
public class ServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<FirstArgumentIsServiceSelector>());
container.Register(Component.For<IModelFactory>().AsFactory(x => x.SelectedWith<FirstArgumentIsServiceSelector>()));
}
}