在 ASP.NET Web API , HttpControllerContext 实例提供了很多关于当前环境的信息,包括当前请求的 URI。
如果服务依赖于此类信息(例如请求 URI),则应该可以将该信息注入(inject)到服务中。
使用Poor Man's DI 很容易做到这一点:只需implement a custom IHttpControllerActivator .
然而,有了温莎城堡,这突然变得非常困难。以前,I've described a very convoluted way解决这个问题,但它取决于 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());
我想知道这是否是解决此问题的最佳方法,或者是否有更好/更简单的方法?
请您参考如下方法:
为了完整起见,我在 Twitter 上从 Krzysztof Koźmic(CaSTLe Windsor 的当前维护者)那里得到的回答表明,问题中概述的方法确实是实现这一特定目标的正确方法。
(但是,我无法链接到该推文,因为 Krzysztof 的推特帐户受到保护(推文不公开可见。))