在ASP.NET的Web API ,HttpControllerContext实例提供了很多关于当前环境下,包括当前请求的URI信息。
如果服务依赖于这样的信息(例如,请求URI),它应该是可以注入该信息到服务。
这是很容易使用穷人的DI做:只是实现自定义IHttpControllerActivator 。
然而,与温莎城堡这个突然变得非常困难。 此前, 我已经描述了一个非常曲折的方式来解决这个问题,但它系于PerWebRequest生活方式,事实证明,这种生活方式不自托管方案工作,因为HttpContext.Current是空的。
到目前为止,我已经能够使这项工作将所需信息作为内嵌参数从自定义IHttpControllerActivator Resolve方法:
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 });
}
然而,在默认情况下,这仅在立即请求的类型依赖于参数(即如果请求控制器本身依赖于工作的baseUri
)。 如果依赖baseUri
的依赖层次埋设较深,但默认情况下不工作,因为内嵌参数不会传播到更深的层次。
这种行为可以用自定义的IDependencyResolver(一温莎城堡的IDependencyResolver,而不是一个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);
}
}
请注意, true
的被传递propagateInlineDependencies
构造函数的参数,而不是false
,这是默认的实现。
为了要连接与InlineDependenciesPropagatingDependencyResolver类一个容器实例,它必须以这种方式来构造:
this.container =
new WindsorContainer(
new DefaultKernel(
new InlineDependenciesPropagatingDependencyResolver(),
new DefaultProxyFactory()),
new DefaultComponentInstaller());
我不知道这是否是对这个问题的最佳解决方案,或者,如果有一个更好/更简单的方法?