NServicebus 与 WebAPI 依赖范围共享嵌套容器

NServicebus share nested container with WebAPI dependency scope

是否可以share/use WebAPI 依赖解析器创建的嵌套容器?

structuremap.web(我使用的是 structuremap 和 NServiceBus.StructureMap 和 UseContainer<StructureMapBuilder>(x => x.ExistingContainer(container)))包提供了 IDependencyResolverIDependencyScope 实现,这些实现非常自我解释 -解析器是用根容器创建的,当请求范围时,它 returns 一个新的范围,它是用根的嵌套容器创建的。

我想知道的是,在 WebAPI 端点的上下文中,我能否与 NSB 共享该嵌套容器。 Looking here,结构图构建器的功能与 WebAPI 解析器的功能几乎相同 - container.GetNestedContainer()。这意味着我为每个使用总线的 (HTTP) 请求获得两个嵌套容器。

我的用例是我想创建一种 headers 桶,我可以将 headers 从 DelegatingHandler 放入,然后将它们从 [= =14=].

此问题也已发布在 google 组 here 上。我快速总结了阅读此问题的人的讨论:

  • NServiceBus 仅在接收消息时创建嵌套容器。通过使用 IBus.Send 或 ASP.NET 管道中的类似方法,NServiceBus 使用它最初配置的容器(例如,用于解析消息突变器)。
  • OWIN HTTP pass through 将传入请求的消息直接放在 queue 上。这也支持自定义扩展(例如添加 headers)。
  • 您可以使用 DI 技巧解决来自不同(嵌套)容器的依赖关系,例如通过使用委托,但涉及一些复杂性。虽然线程静态可用于 DI 欺骗,但请注意,这将随着引入异步 API 的 NServiceBus 版本 6 被打破。
  • IBus 可以包装在一个助手中,该助手可以使用管道当前容器解析并附加 headers.

@Sabacc 总结了 NServiceBus google 组中讨论的可用选项。我们认为 IBus 包装器方法最适合我们的需求。下面是一个示例实现供参考

首先是一个用于添加到 header 存储桶的委托处理程序,此示例添加了授权令牌。如果设置了 header,则会从可通过 HttpRequestMessage.GetDependencyScope() 访问的当前依赖范围解析 HeaderBucket 实例。

public class AuthorizationTokenCapturingHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        AuthenticationHeaderValue header = request.Headers.Authorization;
        if (header != null)
        {
            HeaderBucket bucket = (HeaderBucket)request.GetDependencyScope().GetService(typeof(HeaderBucket));
            bucket.Add(new HeaderBucket.Header(HeaderConstants.AUTHORIZATION_TOKEN, header.Parameter));
        }

        return base.SendAsync(request, cancellationToken);
    }
}

HeaderBucket 在容器配置中配置为瞬态,因此将仅在嵌套容器的生命周期内共享。

IBus 包装器很简单 - 只需包装对 Send 的总线拦截调用,并在发送的消息上设置已添加到存储桶中的 headers。

public class HeaderAwareBus : IHeaderAwareBus
{
    private IBus _bus;
    private HeaderBucket _bucket;

    public HeaderAwareBus(IBus bus, HeaderBucket bucket)
    {
        _bus = bus;
        _bucket = bucket;
    }

    public ICallback Send(object message)
    {
        foreach (HeaderBucket.Header header in _bucket)
        {
            _bus.SetMessageHeader(message, header.Key, header.Value);
        }
        return _bus.Send(message);
    }
}

现在只需将您的控制器依赖项声明为 IHeaderAwareBus,ASP.Net 管道将解决该问题,因此 HeaderBucket 来自从 [=19= 访问的同一嵌套容器]