在Program.cs中注入Keyed Service时遇到依赖问题
解决AddKeyedScoped注入时MediatR不支持键控服务的错误
问题原因
报错的核心是当前使用的MediatR版本不支持键控服务(Keyed Services)。MediatR在自动注册服务的过程中,会遍历所有服务描述符并尝试访问ImplementationType属性,但键控服务的描述符会主动抛出InvalidOperationException,从而触发你看到的错误。
解决方案
1. 升级MediatR到支持键控服务的版本
MediatR从12.0.0版本开始正式支持键控服务,直接升级NuGet包即可解决问题:
- 使用Package Manager Console:
Install-Package MediatR -Version 12.0.0 - 使用.NET CLI:
dotnet add package MediatR --version 12.0.0
升级后无需修改原有的AddKeyedScoped注入代码,直接正常使用即可。
2. 无法升级时,改用工厂类实现服务获取
如果项目依赖限制无法升级MediatR,可以通过自定义工厂类替代键控服务的功能:
// 先单独注册所有支付服务实现类 services.AddScoped<SamanService>(); services.AddScoped<MellatService>(); services.AddScoped<MelliService>(); // 定义支付服务工厂 public class EPaymentServiceFactory { private readonly IServiceProvider _serviceProvider; public EPaymentServiceFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IEPaymentService GetService(string serviceKey) { return serviceKey switch { BackofficeOptions.SamanBankService => _serviceProvider.GetRequiredService<SamanService>(), BackofficeOptions.MellatBankService => _serviceProvider.GetRequiredService<MellatService>(), BackofficeOptions.MelliBankService => _serviceProvider.GetRequiredService<MelliService>(), _ => throw new ArgumentException($"无效的支付服务密钥: {serviceKey}") }; } } // 注册工厂类 services.AddScoped<EPaymentServiceFactory>();
之后在需要使用支付服务的地方,注入EPaymentServiceFactory,调用GetService方法传入对应密钥即可获取目标服务。
3. 临时规避:修改MediatR注册逻辑(不推荐)
这种方式属于hack手段,仅作为临时应急方案:在注册MediatR之前,先将键控服务的描述符从服务集合中移除,注册完成后再加回去。但这种方式容易引发其他问题,不建议长期使用。
总结
优先选择升级MediatR版本,这是最简洁且符合官方规范的解决方案;若无法升级,工厂类方案是更稳定的替代方案。
内容的提问来源于stack exchange,提问作者tohid haghighi
相关产品推荐
相关产品推荐

