NServiceBus 行为的作用域依赖使用

Scoped dependency use from NServiceBus Behavior

我正在尝试使用来自 NServiceBus BehaviorScoped 依赖项。

来自 NServiceBus Behavior 文档:

Behaviors are only created once and the same instance is reused on every invocation of the pipeline. Consequently, every behavior dependency will also behave as a singleton, even if a different option was specified when registering it in dependency injection. Furthermore, the behavior, and all dependencies called during the invocation phase, need to be concurrency safe and possibly stateless. Storing state in a behavior instance should be avoided since it will cause the state to be shared across all message handling sessions. This could lead to unwanted side effects.

由于 Behavior 是一个单例并且 BehaviorInvoke 方法不允许注入任何依赖项(例如 invoke 的方法net 核心中间件,因为在这种情况下它是一个常规接口实现),我不能从这里使用 scoped 依赖项。

我试图通过在构造函数中传递 IServiceCollection 来解决每个 incoming/outgoing 消息在 Invoke 方法中的依赖关系:

private readonly IServiceCollection _services;

public MyIncomingMessageBehavior(IServiceCollection services)
{
    _services = services;
}

public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
{
    var myScopedDependency = _services.BuildServiceProvider().GetService<IMyScopedDependency>();
    // always 
}

:

That's because when you inject IServiceProvider into your middleware - that's "global" provider, not request-scoped. There is no request when your middleware constructor is invoked (middleware is created once at startup), so it cannot be request-scoped container.

总而言之,我的作用域依赖包含当前上下文的数据,我想从我的 Behavior 单例的 Invoke 方法访问这些数据?

有什么办法吗?

您需要在解决依赖关系之前创建一个范围:

private readonly IServiceScopeFactory _scopeFactory;

public MyIncomingMessageBehavior(IServiceScopeFactory scopeFactory)
{
    _scopeFactory = scopeFactory;
}

public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
{
    using(var scope = _scopeFactory.CreateScope())
    {
        var myScopedDependency = scope.ServiceProvider.GetService<IMyScopedDependency>();
    }
}

此外,请注意您的依赖项与范围一起处理。

在您的 Invoke 方法中,您可以使用 var myScopedDependency = context.Builder.Build<IMyScopedDependency>(); 来访问您的作用域依赖项。