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

.NET 9中IKeyedServiceProvider为何需手动注册至DI容器?

.NET 9中IKeyedServiceProvider为何需手动注册至DI容器?

你遇到的这个情况确实挺让人困惑的——明明ServiceProvider实现了IKeyedServiceProvider,官方文档也提到了这一点,但就是不能直接注入。我来帮你理清楚这里面的细节:

1. 报错的核心原因

虽然ServiceProvider本身是IKeyedServiceProvider的实现类,但.NET 9的DI容器并没有把IKeyedServiceProvider加入到自动注册的服务列表中。容器默认只会自动注册IServiceProvider作为可注入服务,所以当你在构造函数里要求注入IKeyedServiceProvider时,容器找不到对应的服务条目,自然就抛出了解析失败的异常。

2. 手动注册可行的原因

你添加的那句手动注册代码:

builder.Services.AddSingleton(provider => (IKeyedServiceProvider)provider);

其实是把当前的ServiceProvider实例(本身就实现了IKeyedServiceProvider),以IKeyedServiceProvider的类型重新注册到容器里。这样容器就能识别并解析这个类型了,这是一个完全合法的临时解决方案,尽管它看起来“多此一举”。

3. 关于已修复的Issue #90528

你提到的那个GitHub Issue其实解决的是另一个问题:它让IServiceProvider具备了调用GetKeyedService方法获取键控服务的能力,但并没有解决IKeyedServiceProvider本身的自动注册问题。所以即使那个Issue被修复了,你现在遇到的注入问题依然存在——这是两个独立的功能点。

4. 当前.NET 9的预期行为

根据.NET 9的当前设计,IKeyedServiceProvider确实需要手动注册才能注入,这和IServiceProvider的自动可用行为形成了明显的不一致,也和文档描述给人的直觉不符。不过社区已经多次反馈这个问题,官方团队大概率会在后续的.NET版本(比如.NET 10)中调整这个设计,让IKeyedServiceProvider也能像IServiceProvider一样自动被容器识别。

5. 不需要手动注册的替代方案

如果你不想添加额外的注册代码,也可以通过注入IServiceProvider,然后在代码中将其强制转换为IKeyedServiceProvider来使用,效果是一样的:

[ApiController]
[Route("[controller]")]
public class CatalogController(CatalogDbContext context, IServiceProvider serviceProvider) : ControllerBase
{
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var keyedProvider = (IKeyedServiceProvider)serviceProvider;
        var service = keyedProvider.GetRequiredKeyedService<IProductService>("ProductService1");
        var products = await context.Products.ToListAsync();
        return Ok(products);
    }
}

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 12:37:58