You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 03:22:56