NServicebus共享具有WebAPI依赖范围的嵌套容器

本文关键字:嵌套 范围 依赖 共享 WebAPI NServicebus | 更新日期: 2023-09-27 18:21:21

是否可以共享/使用WebAPI依赖解析程序创建的嵌套容器?

structuremap.web(我使用的是structuremap和NServiceBus.structuremap和UseContainer<StructureMapBuilder>(x => x.ExistingContainer(container)))包提供了非常不言自明的IDependencyResolverIDependencyScope实现-解析器是用根容器创建的,当请求作用域时,它会返回一个新作用域,该作用域是用根的嵌套容器创建的。

我想知道的是,在WebAPI端点的上下文中,我可以与NSB共享该嵌套容器吗。从这里看,结构映射生成器所做的工作与WebAPI解析器所做的差不多——容器。GetNestedContainer()。这意味着我为使用总线的每个(HTTP)请求获得两个嵌套容器。

我的用例是,我想创建一种headers bucket,可以将headers从DelegatingHandler中放入,然后在OutgoingMessageMutator中取出。

NServicebus共享具有WebAPI依赖范围的嵌套容器

这个问题也发布在这里的谷歌小组上。我很快为阅读这个问题的人总结了讨论:

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

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

首先是一个用于添加到头存储桶的委派处理程序,本例添加授权令牌。如果设置了标头,则从可通过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的调用,并设置已添加到正在发送的消息的bucket中的头。

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管道将从DelegatingHandler 访问的同一嵌套容器中解析该依赖项,从而解析HeaderBucket