使用 Castle Windsor 解析 HttpRequestMessage
Resolving HttpRequestMessage with Castle Windsor
我尝试遵循现有帖子的建议,使 HttpRequestMessage
可用作 Web 服务的构造函数依赖项 API:
如果如果所有的依赖项只有一个构造函数,这个建议工作正常。但是当一个依赖有多个构造函数时,依赖解析失败。
关于如何扩展这个想法以使用多个构造函数有什么想法吗?
=========================
现有的做法总结如下:
首先,在解析 IHttpControllerActivator
:
中的控制器时,将 HttpRequestMessage
添加为附加命名参数
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var controller = (IHttpController)container.Resolve(
controllerType,
new { request });
然后你在CreationContext
中传播这个论点:
public class InlineDependenciesPropagatingDependencyResolver :
DefaultDependencyResolver
{
protected override CreationContext RebuildContextForParameter(
CreationContext current,
Type parameterType)
{
if (parameterType.ContainsGenericParameters)
{
return current;
}
return new CreationContext(parameterType, current, true);
}
}
当所有依赖项只有一个构造函数时,这工作正常。
就我而言,我有一个依赖层次结构:
- 控制器依赖于
IServiceA
ServiceA
取决于 IServiceB
ServiceB
取决于 IServiceC
ServiceC
取决于 HttpRequestMessage
其中 ServiceC
看起来像这样:
public class ServiceC: IServiceC
{
private readonly HttpRequestMessage request;
public ServiceC(HttpRequestMessage request)
{
this.request = request;
}
而ServiceB
有两个构造函数:
public class ServiceB: IServiceB
{
public ServiceB(string paramForTests)
{
// Do stuff
}
public ServiceB(IServiceC serviceC)
{
// Do stuff
}
但随后温莎未能解析 ServiceC
。
问题似乎出在 DefaultComponentActivator. It calls into the CanResolve
method in DefaultDependencyResolver 的 SelectEligibleConstructor
逻辑中,最终结束于:
protected virtual bool CanResolveFromKernel(CreationContext context, ComponentModel model, DependencyModel dependency)
{
if (dependency.ReferencedComponentName != null)
{
// User wants to override
return HasComponentInValidState(dependency.ReferencedComponentName, dependency, context);
}
if (dependency.Parameter != null)
{
return true;
}
if (typeof(IKernel).IsAssignableFrom(dependency.TargetItemType))
{
return true;
}
if (dependency.TargetItemType.IsPrimitiveType())
{
return false;
}
return HasAnyComponentInValidState(dependency.TargetItemType, dependency, context);
}
然后HasAnyComponentInValidState
只是看ServiceC
是否已经解决,并没有真正检查是否可以解决。
如果只有一个构造函数,则代码调用 Resolve
方法,正确递归解析依赖关系,ServiceC 可用。
我不想将我的服务限制为只有一个构造函数(或者使用 [DoNotSelect]
属性只留下一个给 Castle 查看)。
有什么想法可以像我一样注入参数,并且仍然可以使用多个构造函数吗?
我找到了另一种解析 HttpRequestMessage
参数的方法,现在可以使用了。
只需使用工厂方法来启动依赖于 HttpRequestMessage
的服务,您可以在其中从控制器激活器向下传递的上下文中手动提取所需的 "request" 参数:
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<IServiceC>()
.UsingFactoryMethod((kernel, context) => {
var request = (HttpRequestMessage)context.AdditionalArguments["request"];
var serviceC = new ServiceC(request);
return serviceC;
})
.LifestyleTransient()
);
}
}
我尝试遵循现有帖子的建议,使 HttpRequestMessage
可用作 Web 服务的构造函数依赖项 API:
如果如果所有的依赖项只有一个构造函数,这个建议工作正常。但是当一个依赖有多个构造函数时,依赖解析失败。
关于如何扩展这个想法以使用多个构造函数有什么想法吗?
=========================
现有的做法总结如下:
首先,在解析 IHttpControllerActivator
:
HttpRequestMessage
添加为附加命名参数
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var controller = (IHttpController)container.Resolve(
controllerType,
new { request });
然后你在CreationContext
中传播这个论点:
public class InlineDependenciesPropagatingDependencyResolver :
DefaultDependencyResolver
{
protected override CreationContext RebuildContextForParameter(
CreationContext current,
Type parameterType)
{
if (parameterType.ContainsGenericParameters)
{
return current;
}
return new CreationContext(parameterType, current, true);
}
}
当所有依赖项只有一个构造函数时,这工作正常。
就我而言,我有一个依赖层次结构:
- 控制器依赖于
IServiceA
ServiceA
取决于IServiceB
ServiceB
取决于IServiceC
ServiceC
取决于HttpRequestMessage
其中 ServiceC
看起来像这样:
public class ServiceC: IServiceC
{
private readonly HttpRequestMessage request;
public ServiceC(HttpRequestMessage request)
{
this.request = request;
}
而ServiceB
有两个构造函数:
public class ServiceB: IServiceB
{
public ServiceB(string paramForTests)
{
// Do stuff
}
public ServiceB(IServiceC serviceC)
{
// Do stuff
}
但随后温莎未能解析 ServiceC
。
问题似乎出在 DefaultComponentActivator. It calls into the CanResolve
method in DefaultDependencyResolver 的 SelectEligibleConstructor
逻辑中,最终结束于:
protected virtual bool CanResolveFromKernel(CreationContext context, ComponentModel model, DependencyModel dependency)
{
if (dependency.ReferencedComponentName != null)
{
// User wants to override
return HasComponentInValidState(dependency.ReferencedComponentName, dependency, context);
}
if (dependency.Parameter != null)
{
return true;
}
if (typeof(IKernel).IsAssignableFrom(dependency.TargetItemType))
{
return true;
}
if (dependency.TargetItemType.IsPrimitiveType())
{
return false;
}
return HasAnyComponentInValidState(dependency.TargetItemType, dependency, context);
}
然后HasAnyComponentInValidState
只是看ServiceC
是否已经解决,并没有真正检查是否可以解决。
如果只有一个构造函数,则代码调用 Resolve
方法,正确递归解析依赖关系,ServiceC 可用。
我不想将我的服务限制为只有一个构造函数(或者使用 [DoNotSelect]
属性只留下一个给 Castle 查看)。
有什么想法可以像我一样注入参数,并且仍然可以使用多个构造函数吗?
我找到了另一种解析 HttpRequestMessage
参数的方法,现在可以使用了。
只需使用工厂方法来启动依赖于 HttpRequestMessage
的服务,您可以在其中从控制器激活器向下传递的上下文中手动提取所需的 "request" 参数:
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<IServiceC>()
.UsingFactoryMethod((kernel, context) => {
var request = (HttpRequestMessage)context.AdditionalArguments["request"];
var serviceC = new ServiceC(request);
return serviceC;
})
.LifestyleTransient()
);
}
}