In the ASP.NET Web API http://www.asp.net/web-api,HttpControllerContext实例提供了很多有关当前环境的信息,包括当前请求的URI。
如果服务依赖于此类信息(例如请求 URI),则应该可以将该信息注入到服务中。
使用 Poor Man 的 DI 可以很容易地做到这一点:只需实现自定义 IHttpControllerActivator http://blog.ploeh.dk/2012/04/17/InjectingHttpControllerContextWithTheASPNETWebAPI.aspx.
然而,有了温莎城堡,这突然变得非常困难。之前,我已经描述了一种非常复杂的方式 http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx解决这个问题,但这取决于 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(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
,这是默认实现。
为了将容器实例与 InlineDependencyPropagatingDependencyResolver 类连接起来,必须按以下方式构造它:
this.container =
new WindsorContainer(
new DefaultKernel(
new InlineDependenciesPropagatingDependencyResolver(),
new DefaultProxyFactory()),
new DefaultComponentInstaller());
我想知道这是否是解决这个问题的最佳方法,或者是否有更好/更简单的方法?