问题
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