在ASP.NET Web API中,HttpControllerContext 实例提供了很多关于当前环境的信息,包括当前请求的 URI。
如果服务依赖于此类信息(例如请求 URI),则应该可以将该信息注入到服务中。
使用 Poor Man 的 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 });
}
但是,默认情况下,这仅在立即请求的类型依赖于参数时才有效(即,如果请求的 Controller 本身依赖于baseUri
)。如果依赖关系在baseUri
依赖层次结构中更深,则默认情况下它不起作用,因为内联参数不会传播到更深层。
可以使用自定义 IDependencyResolver(Castle Windsor 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());
我想知道这是否是解决此问题的最佳方法,或者是否有更好/更简单的方法?