.NET 6中如何通过依赖注入注册并检索任意数量的类?
解决方案
1. 确定统一的处理器接口
优先选择非泛型接口方案,泛型接口会导致每个处理器的接口类型不一致,大幅增加DI注册和字典构建的复杂度。修正后的接口定义如下:
public interface IColorHandler { // 只读属性,标识当前处理器负责的枚举值 Color HandledColor { get; } Task<string> GetContent(GeneralParamsObject info); }
2. 实现具体处理器类
每个处理器类只需实现上述接口,并明确指定对应的HandledColor:
public class GreenHandler : IColorHandler { public Color HandledColor => Color.Green; public Task<string> GetContent(GeneralParamsObject info) { // 编写对应颜色的业务逻辑 return Task.FromResult("针对绿色的内容"); } } // 其他颜色处理器同理,比如BlueHandler、RedHandler等
3. 依赖注入注册配置
分两步完成注册:先扫描并注册所有处理器,再构建并注册字典:
第一步:扫描注册所有处理器
沿用你现有的扫描方式,将所有实现IColorHandler的类注册为Scoped生命周期:
serviceCollection.Scan(scan => scan .FromAssemblies(AppDomain.CurrentDomain.GetAssemblies()) .AddClasses(classes => classes.AssignableTo<IColorHandler>()) .As<IColorHandler>() .WithScopedLifetime());
第二步:注册字典实例
通过工厂方式,从DI容器中获取所有处理器实例,转换为以枚举为键的字典,同时添加重复键校验提前暴露问题:
serviceCollection.AddScoped<IDictionary<Color, IColorHandler>>(sp => { var allHandlers = sp.GetServices<IColorHandler>(); // 校验是否存在重复的枚举处理器 var duplicateHandlers = allHandlers .GroupBy(handler => handler.HandledColor) .Where(group => group.Count() > 1) .Select(group => group.Key); if (duplicateHandlers.Any()) { throw new InvalidOperationException($"存在重复的颜色处理器,枚举值:{string.Join(", ", duplicateHandlers)}"); } return allHandlers.ToDictionary(handler => handler.HandledColor); });
4. 主服务使用字典
你的ColorContentService代码无需修改,直接注入字典即可使用:
public class ColorContentService : IColorContentService { private readonly IDictionary<Color, IColorHandler> _handlers; public ColorContentService(IDictionary<Color, IColorHandler> handlers) { _handlers = handlers; } public async Task<string> GetColorsContent(List<Color> colors) { var info = BuildInfoObject(); var content = new StringBuilder(); foreach (var color in colors) { if (_handlers.TryGetValue(color, out var handler)) { content.AppendLine(await handler.GetContent(info)); } } return content.ToString(); } private GeneralParamsObject BuildInfoObject() { // 构建参数对象的逻辑 return new GeneralParamsObject(); } }
关键说明
- 生命周期匹配:字典和处理器都使用Scoped生命周期,确保每次请求中处理器的实例一致性
- 性能优化:字典的
TryGetValue是O(1)操作,远快于遍历IEnumerable的O(n),适合百级数量的处理器场景 - 兼容性:所有API均支持.NET 6,无需使用后续版本的新特性
内容的提问来源于stack exchange,提问作者Sabelyn
相关产品推荐
相关产品推荐

