After using ninject for a short project (some modifications to a Subtext blog) I came back to Windsor and found myself missing ToMethod(). ToMethod() in ninject gives you factory method support, that is, you pass it a Func and the container will call it whenever it needs to instantiate the component.
Now Windsor has had factory support for years, but it requires the factory to be a class, registered as a component in the container. This is ok as it's the most flexible approach, but sometimes all you need is a factory method, and creating a class and then registering it seems a bit overkill. It would be nicer to write something like:
Container.Register(Component.For<HttpServerUtilityBase>() .FactoryMethod(() => new HttpServerUtilityWrapper(HttpContext.Current.Server)) .LifeStyle.Is(LifestyleType.Transient));
With this little extension method, you can do just that:
public static class ComponentRegistrationExtensions { public static IKernel Kernel { private get; set; } public static ComponentRegistration<T> FactoryMethod<T, S>(this ComponentRegistration<T> reg, Func<S> factory) where S: T { var factoryName = typeof(GenericFactory<S>).FullName; Kernel.Register(Component.For<GenericFactory<S>>().Named(factoryName).Instance(new GenericFactory<S>(factory))); reg.Configuration(Attrib.ForName("factoryId").Eq(factoryName), Attrib.ForName("factoryCreate").Eq("Create")); return reg; } private class GenericFactory<T> { private readonly Func<T> factoryMethod; public GenericFactory(Func<T> factoryMethod) { this.factoryMethod = factoryMethod; } public T Create() { return factoryMethod(); } } }
Of course, this needs the FactorySupportFacility to be installed:
Container.AddFacility("factory.support", new FactorySupportFacility());
And since this isn't really a part of the Kernel, it needs a reference to the container's kernel:
ComponentRegistrationExtensions.Kernel = Container.Kernel;
UPDATE 5/7/2009: I submitted a patch which Ayende applied in revision 5650 so this is now part of the Windsor trunk, only instead of FactoryMethod() it's called UsingFactoryMethod()
UPDATE 7/30/2010: as of Windsor 2.5, UsingFactoryMethod() no longer requires the FactorySupportFacility.