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

时间:2015-11-10 23:02:25

标签: c# asp.net-web-api dependency-injection nservicebus structuremap

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

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

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

我的用例是,我想创建一种标题存储桶,我可以将标题放入DelegatingHandler,然后将其从OutgoingMessageMutator中拉出来。

2 个答案:

答案 0 :(得分:1)

此问题也已发布在Google群组here上。我很快总结了人们阅读这个问题的讨论:

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

答案 1 :(得分:1)

@Sabacc已经总结了NServiceBus google组中讨论的可用选项。我们认为IBus包装器方法最符合我们的需求。以下是此参考的示例实现

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

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中,并设置已添加到正在发送的消息中的存储桶的标头。

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 DelegatingHandler >