In the ASP.NET Web API, HttpControllerContext instances provide a lot of information about the current environment, including the URI of the current request.
If a service relies on such information (e.g. the request URI), it should be possible to inject that information into the service.
This is pretty easy to do using Poor Man's DI: just implement a custom IHttpControllerActivator.
However, with Castle Windsor this suddenly becomes very difficult. Previously, I've described a very convoluted way to resolve this issue, but it hinges on the PerWebRequest lifestyle, and it turns out that this lifestyle doesn't work in self-hosting scenarios, because HttpContext.Current is empty.
So far, I've been able to make this work by passing the desired information as an inline argument to the Resolve method from a custom IHttpControllerActivator:
public IHttpController Create(
HttpControllerContext controllerContext,
Type controllerType)
{
var baseUri = new Uri(
controllerContext
.Request
.RequestUri
.GetLeftPart(UriPartial.Authority));
return (IHttpController)this.container.Resolve(
controllerType,
new { baseUri = baseUri });
}
However, by default, this only works if the immediately requested type relies on the argument (i.e. if the requested Controller itself depends on the baseUri
). If the dependency on baseUri
is buried deeper in the dependency hierarchy, it doesn't work by default, because inline arguments aren't propagated to deeper layers.
This behavior can be changed with a custom IDependencyResolver (a Castle Windsor IDependencyResolver, not an ASP.NET Web API IDependencyResolver):
public class InlineDependenciesPropagatingDependencyResolver :
DefaultDependencyResolver
{
protected override CreationContext RebuildContextForParameter(
CreationContext current, Type parameterType)
{
if (parameterType.ContainsGenericParameters)
{
return current;
}
return new CreationContext(parameterType, current, true);
}
}
Notice that true
is being passed as the propagateInlineDependencies
constructor argument instead of false
, which is the default implementation.
In order to wire up a container instance with the InlineDependenciesPropagatingDependencyResolver class, it must be constructed in this way:
this.container =
new WindsorContainer(
new DefaultKernel(
new InlineDependenciesPropagatingDependencyResolver(),
new DefaultProxyFactory()),
new DefaultComponentInstaller());
I'm wondering if this is the best solution to this problem, or if there's a better/simpler way?