在ASP.NET Web API中,HttpControllerContext实例提供了关于当前环境的大量信息,包括当前请求的URI。
如果服务依赖于这些信息(例如请求URI),则应该可以将该信息注入到服务中。
使用Poor Man's DI很容易做到这一点:只需实现自定义的IHttpControllerActivator即可。
然而,使用Castle Windsor就变得非常困难。以前,我描述了一种非常复杂的方法来解决这个问题,但它依赖于PerWebRequest生命周期,并且结果发现,这个生命周期在自托管场景中无法工作,因为HttpContext.Current为空。
到目前为止,我已经通过将所需的信息作为内联参数传递给来自自定义IHttpControllerActivator的Resolve方法,使其能够正常工作:
然而,默认情况下,只有在立即请求的类型依赖于参数时(即如果请求的控制器本身依赖于
可以通过自定义IDependencyResolver(Castle Windsor IDependencyResolver,而不是ASP.NET Web API IDependencyResolver)来更改此行为:
请注意,构造函数参数
要将容器实例与
如果服务依赖于这些信息(例如请求URI),则应该可以将该信息注入到服务中。
使用Poor Man's DI很容易做到这一点:只需实现自定义的IHttpControllerActivator即可。
然而,使用Castle Windsor就变得非常困难。以前,我描述了一种非常复杂的方法来解决这个问题,但它依赖于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);
}
}
请注意,构造函数参数
propagateInlineDependencies
传递的是true
,而不是默认实现false
。要将容器实例与
InlineDependenciesPropagatingDependencyResolver
类连接起来,必须以此方式构建它:this.container =
new WindsorContainer(
new DefaultKernel(
new InlineDependenciesPropagatingDependencyResolver(),
new DefaultProxyFactory()),
new DefaultComponentInstaller());
我在想这是否是解决这个问题的最佳方案,或者是否有更好/更简单的方法?