我正在尝试创建一个作为后台服务运行的依赖注入管道服务。 我的想法是,我可以创建“一对多”这些服务,并为每个步骤中需要更改的一些值(使用服务密钥加载)传入简单的 IOption 配置,我将它们注册为一个密钥服务,这样它们就不会覆盖彼此。 我还有一个作为单例创建的队列管理器,它允许我根据也在 IOptions 配置中传递的队列配置获取生产者/消费者。
我为要创建的管道的每个版本传递不同的服务密钥
我的代码的简单版本(下面只是基础知识)
public IServiceCollection AddPipelineService(this IServiceCollection services,
IConfigurationManager configuration, string serviceKey)
{
// Get Config for the steps based on the sevice key
var StepOptions = Options.Create(
configuration
.GetSection($"{serviceKey}:{StepOptions.StepOptionsName}")
.Get<MessageFactoryOptions>());
// Build a list of steps and reister a service
services.AddKeyedSingleton<IStep, Step1>(serviceKey, (p,o) => new Step1(p.GetRequiredService<ILogger<ConfirmResponseMessageFactory>>(), stepOptions);
services.AddKeyedSingleton<IStep, Step2>(serviceKey, (p, o) => new Step2(p.GetRequiredService<ILogger<ConfirmResponseMessageFactory>>(), stepOptions);
services.AddKeyedSingleton<IStep, Step3>(serviceKey, (p, o) => new Step3(p.GetRequiredService<ILogger<ConfirmResponseMessageFactory>>(), stepOptions);
// Create the service provider
var provider = services.BuildServiceProvider(validateScopes: true);
// Add the steps to a set collection
IEnumerable<IStep> steps = provider.GetKeyedServices<IMessageProcessItem>(serviceKey);
services.AddKeyedSingleton<IStepCollection, StepCollection>(serviceKey, (p, o) => new StepCollection(steps));
// Create the queue options based on the service key
var queueOptions = Options.Create(
configuration
.GetSection($"{serviceKey}:{QueueOptions.QueueOptionsName}")
.Get<MessageFactoryOptions>());
// NOTE
// IQueueManager registered earlier as a singleton (i only want to onpen a siingle connection and reuse for creation of consumers and producers)
// PipelineBackgroundService is a BackgroundService
services.AddSingleton<IHostedService, PipelineBackgroundService>(
p => new PipelineBackgroundService(
p.GetRequiredService<ILogger<PipelineBackgroundService>>(),
p.GetRequiredService<IQueueManager>(),
p.GetRequiredKeyedService<IStepCollection>(serviceKey),
queueOptions);
return services;
}
所有这些都有效,但我最终得到了多个版本的队列管理器,因为我调用BuildServiceProvider
,我相信它创建了一个新容器。 但我读过我应该避免使用BuildServiceProvider 有没有一种方法可以在不产生这种副作用并且不使用 BuildServiceProvider 的情况下做到这一点。
谢谢, 尼克
services.AddKeyedSingleton<IStepCollection, StepCollection>(serviceKey,
(p, o) => new StepCollection(p.GetKeyedServices<IMessageProcessItem>(serviceKey)));
现在只创建了 QueueManager 的一个实例