在 C# 中使用通道时,我想运行具有相同基本类型的多个通道,但这会导致 DI 出现问题。比如说
我想要一个高优先级通道和一个中优先级通道,两者都是问题类型。因此将其设置为 DI 它看起来像
services.AddSingleton(channel.CreateUnbounded<Issue>()) // high priority
services.AddSingleton(channel.CreateUnbounded<Issue>()) // normal priority?
public async Task<bool> CreateHighPriorityIssues(Channel<Issue> channel) {}
public async Task<bool> CreateNormalPriorityIssues(Channel<Issue> channel) {}
上面的方法显然行不通,那么我该如何在不重构所有基类的情况下进行呢?
我能想到的唯一其他选择是实现某种工厂方法。
根据研究,使用 Microsoft 的内置 DI 框架并没有简单的方法来做到这一点,尽管该框架易于使用,但功能并不像某些第三方 DI 框架那样丰富。
为此,我决定改用 Autofac,它为我提供了通过命名服务调用正确服务所需的灵活性。
https://autofac.readthedocs.io/en/latest/advanced/keyed-services.html
你能不能简单地添加两个接口:
IIssueHighPriority { //members needed from Issue }
IIssueLowPriority { //members needed from Issue }
将两个接口应用到Issue类。
public class Issue : IIssueHighPriority, IIssueLowPriority
在 Di 中设置两个通道:
services.AddSingleton(channel.CreateUnbounded<IIssueHighPriority>())
services.AddSingleton(channel.CreateUnbounded<IIssueLowPriority>())
您的“上游服务”可以决定优先级,并排队到正确的通道。
if(needToProcessAsPriority)
channelWriterHighPriority.TryWrite(issue);
else
channelWriterLowPriority.TryWrite(issue);
worker 服务可以在其构造函数中指定两个 Channel,它将通过 DI 注入,并可以根据需要处理它们。
public class WorkerService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
//Process from both Channels as required:
while (await highPriorityQueueReader.WaitToReadAsync(stoppingToken))
{
//do important things
}
while (await lowPriorityQueueReader .WaitToReadAsync(stoppingToken))
{
//do less important things
}
}
}
public WorkerService(Channel<IIssueHighPriority> highPriority, Channel<IIssueLowPriority> lowPriority)
{
highPriorityQueueReader = highPriority.Reader;
lowPriorityQueueReader = lowPriority.Reader;
}
ChannelReader<IIssueHighPriority> highPriorityQueueReader { get; }
ChannelReader<IIssueLowPriority> lowPriorityQueueReader { get; }
}