问题
I'm having an issue with getting the same instance of the IIdentityService(my own class) or IServiceProvider in my consumer observer. I have an identity service where I set the credentials for the user, which is used later in the consumer pipeline.
I have tried the code below along with other code and configuration changes.
_serviceProvider.GetRequiredService<IIdentityService>()
_serviceProvider.CreateScope()
var consumerScopeProvider = _serviceProvider.GetRequiredService<IConsumerScopeProvider>();
using (var scope = consumerScopeProvider.GetScope(context))
{
// this next line of code is where we must access the payload
// using a container specific interface to get access to the
// scoped IServiceProvider
var serviceScope = scope.Context.GetPayload<IServiceScope>();
var serviceProviderScoped = serviceScope.ServiceProvider;
IIdentityService identityService = _serviceProvider.GetRequiredService<IIdentityService>();
}
// Also tried this as Scoped
services.AddTransient<CustomConsumer>();
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(new Uri(busConfiguration.Address), h =>
{
h.Username(busConfiguration.Username);
h.Password(busConfiguration.Password);
});
cfg.ReceiveEndpoint(host, "queue_1", endpointCfg => ConfigureConsumers(endpointCfg, provider));
cfg.UseServiceScope(provider);
});
busControl.ConnectConsumeObserver(new ConsumeObserver(provider));
public class ConsumeObserver : IConsumeObserver
{
private readonly IServiceProvider _serviceProvider;
public ConsumeObserver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
Task IConsumeObserver.PreConsume<T>(ConsumeContext<T> context)
{
var identityMessage = (IIdentityMessage)context.Message;
if (identityMessage == null)
{
return Task.CompletedTask;
}
// Here I get a "Cannot resolve scoped service '' from root provider." error
IIdentityService identityService = _serviceProvider.GetRequiredService<IIdentityService>();
var task = identityService.SetIdentityAsync(identityMessage.Identity.TenantIdentifier, identityMessage.Identity.UserIdentifier);
// This gets a different instance of the IIdentityService.cs service.
//IIdentityService identityService = _serviceProvider.CreateScope().ServiceProvider.GetRequiredService<IIdentityService>();
// called before the consumer's Consume method is called
return task;
}
Task IConsumeObserver.PostConsume<T>(ConsumeContext<T> context)
{
// called after the consumer's Consume method is called
// if an exception was thrown, the ConsumeFault method is called instead
return TaskUtil.Completed;
}
Task IConsumeObserver.ConsumeFault<T>(ConsumeContext<T> context, Exception exception)
{
// called if the consumer's Consume method throws an exception
return TaskUtil.Completed;
}
}
// This is where I need to identity credentials
services.AddScoped<UserContext>((provider =>
{
// This gets a different instance of IIdentityService
var identityService = provider.GetRequiredService<IIdentityService>();
var contextProvider = provider.GetRequiredService<IContextProvider>();
var identity = identityService.GetIdentity();
return contextProvider.GetContext(identity.UserId);
}));
var task = identityService.SetIdentityAsync(identityMessage.Identity.TenantIdentifier, identityMessage.Identity.UserIdentifier);
The setting of the identity above should be retrievable below.
var identity = identityService.GetIdentity();
What I get is null reference as the service provider is of a different instance.
Can anyone tell me how to get the same instance of the service provider through out the consumer pipeline?
来源:https://stackoverflow.com/questions/55957555/getting-masstransit-to-use-scoped-lifetime