Scoped dependency use from NServiceBus Behavior

时光毁灭记忆、已成空白 提交于 2020-05-29 10:57:23

问题


I'm trying to use a Scoped dependency from a NServiceBus Behavior.

From NServiceBus Behavior docs:

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.

Since a Behavior is a Singleton and the Invoke method of the Behavior doesn't allow to inject any dependency (such as the invoke method of a net core middleware because in this case it's a regular interface implementation), I can't use a scoped dependency from here.

I've tried to resolve my dependencies in my Invoke method for each incoming/outgoing message by passing IServiceCollection in the constructor:

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 
}

But this doesn't work:

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.

In summary, my scoped dependency contains data for the current context and I'd like to access this data from the Invoke method of my Behavior singleton?

Is there any way to do it?


回答1:


You need to create a scope before resolving your dependency:

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

Also, pay attention that your dependency is disposed along with scope.




回答2:


In your Invoke method you can use var myScopedDependency = context.Builder.Build<IMyScopedDependency>(); to gain access to your scoped dependencies.



来源:https://stackoverflow.com/questions/52606124/scoped-dependency-use-from-nservicebus-behavior

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!