I am trying to set up Castle Windsor with ASP.NET WebAPI.
I am also using the Hyprlinkr package (https://github.com/ploeh/Hyprlinkr) and so need an instance of HttpR
Here's a Composition Root that works for me:
public class WindsorCompositionRoot : IHttpControllerActivator
{
private readonly IWindsorContainer container;
public WindsorCompositionRoot(IWindsorContainer container)
{
this.container = container;
}
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var controller = (IHttpController)this.container.Resolve(
controllerType,
new
{
request = request
});
request.RegisterForDispose(
new Release(
() => this.container.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action release;
public Release(Action release)
{
this.release = release;
}
public void Dispose()
{
this.release();
}
}
}
Here's how I create the container:
this.container =
new WindsorContainer(
new DefaultKernel(
new InlineDependenciesPropagatingDependencyResolver(),
new DefaultProxyFactory()),
new DefaultComponentInstaller())
.Install(new MyWindsorInstaller());
and here's the InlineDependenciesPropagatingDependencyResolver:
public class InlineDependenciesPropagatingDependencyResolver :
DefaultDependencyResolver
{
protected override CreationContext RebuildContextForParameter(
CreationContext current,
Type parameterType)
{
if (parameterType.ContainsGenericParameters)
{
return current;
}
return new CreationContext(parameterType, current, true);
}
}
Finally, here's how I register RouteLinker:
container.Register(Component
.For<RouteLinker, IResourceLinker>()
.LifestyleTransient());
One thing to be aware of is that the ApiController base class has a public property named Request
of the HttpRequestMessage type. As explained in section 10.4.3 of my book Windsor will attempt to assign a value to each writeable property if it has a matching component - and that match is case-insensitive.
When you pass an HttpRequestMessage named request
to the Resolve method, this is exactly what happens, so you need to tell Castle Windsor that it should forego Property Injection for ApiControllers. Here's how I don that in a convention-based registration:
container.Register(Classes
.FromThisAssembly()
.BasedOn<IHttpController>()
.ConfigureFor<ApiController>(c => c.Properties(pi => false))
.LifestyleTransient());
Why not to use already built-in mechanism in ASP.NET Web API - Dependency resolver
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
In project WebApiContrib there is CastleWindsor resolver implementation, but as I've seen with Dependency resolver
https://github.com/WebApiContrib/WebApiContrib.IoC.CastleWindsor
And as Mark said in comment - one of the ways to implement IHttpControllerActivator
http://blog.ploeh.dk/2012/10/03/DependencyInjectionInASPNETWebAPIWithCastleWindsor.aspx