我已尝试按照现有帖子的建议,使HttpRequestMessage
可用作Web API中服务的构造函数依赖项:
ASP Web Api - IoC - Resolve HttpRequestMessage
Resolving HttpControllerContext with Castle Windsor
如果所有依赖项只有一个构造函数,那么这个建议可以正常运行。但是,当依赖项具有多个构造函数时,依赖项解析将失败。
如何扩展这个想法以使用多个构造函数的任何想法?
=======================
现有方法总结如下:
首先在解析HttpRequestMessage
中的控制器时添加IHttpControllerActivator
作为额外的命名参数:
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的SelectEligibleConstructor
逻辑中。它调用了DefaultDependencyResolver中的CanResolve
方法,该方法最终结束于:
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查看)。
如何按照我的方式注入参数,并且仍然可以使用多个构造函数吗?
答案 0 :(得分:0)
我找到了解决HttpRequestMessage
参数的另一种方法,该方法现在可以使用。
只需使用工厂方法来启动依赖于HttpRequestMessage
的服务,您就可以在此方法中从控制器激活器传递的上下文中手动提取所需的“请求”参数:
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()
);
}
}