使用 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 DefaultDependencyResolverSelectEligibleConstructor 逻辑中,最终结束于:

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()
        );
    }
}