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 se
Just for the sake of completeness, an answer I got from Krzysztof Koźmic (the current maintainer of Castle Windsor) on Twitter indicated that the method outlined in the question is, indeed, the correct way of achieving this particular goal.
(However, I can't link to that tweet, since Krzysztof's twitter account is protected (tweets are not publicly visible.))
It seems to me that your InlineDependenciesPropagatingDependencyResolver is actually masking something fairly critical to the architecture of your application: that one or more of your components have dependencies that cannot be reliably resolved statically, from the container, or from dynamic context.
It violates the assumption most developers would make when passing inline dependencies to Resolve() (that they only get passed down one level of dependency resolution) and in certain scenarios could cause a dependency to incorrectly override some other configured service. (E.g. if you had another component many levels down which had a dependency of the same type and name). It could be a potential cause of bugs that would be very difficult to identify.
The issue at the heart of this is a difficult one for DI and really indicates that IoC is not really feasible (i.e. our dependency(ies) need to be 'pushed' and cannot be 'pulled' for us by the container). It seems to me there are two options:
1) rectify the problem that is preventing 'inversion'. i.e. wrap the HttpControllerContext/HttpContext, augment that wrapper to behave as required in a self-hosted scenario and have your components rely on that wrapper, rather than HttpControllerContext/HttpContext directly.
2) reflect the shortcomings of the environment you are working with (that it doesn't fully support 'inversion') and make the workaround to handle those shortcomings very explicit. In your scenario this would probably involve utilising a typed factory (interface) to instantiate the component requiring a baseUri
in your IHttpControllerActivator.Create()
. This would mean that if this component was further down the dependency hierarchy, you would need to explicitly build up your dependency hierarchy until you had your controller.
I would probably go for the second option simply because when conventions don't cut it I prefer to be as explicit as possible.
UPDATED
Assuming we had a controller type A
, which relied on component B
, which in turn relied on the baseUri, the second option might look something like:
// Typed factories for components that have dependencies, which cannot be resolved statically
IBFactory bFactory;
IAFactory aFactory;
public IHttpController Create(HttpControllerContext controllerContext, Type controllerType)
{
if (controllerType == typeof(A))
{
// Special handling for controller where one or more dependencies
// are only available via controllerContext.
var baseUri = new Uri(controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Authority));
B b = this.bFactory.Create(baseUri);
return this.aFactory.Create(b);
}
// Default for all other controllers
return (IHttpController)this.container.Resolve(controllerType);
}
The key points are that this explicitly deals with the shortcomings of our environment, it binds the affected types specifically with the dependency overrides we provide imperatively and ensures that we are not accidentally overriding any other dependencies.