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

ASP.NET Core多单例获取含Scoped依赖的Transient服务异常问题

ASP.NET Core 单例依赖注入异常问题

问题场景

在ASP.NET Core中注册两个单例服务SingletonA和SingletonB,两者都通过服务提供者调用GetRequiredService<TransientServiceA>()获取依赖。TransientServiceA的构造函数依赖Scoped服务ScopedServiceA。出现的异常情况是:仅注册其中一个单例时,依赖注入能正常工作;同时注册两个单例时,抛出无法解析TransientServiceA的错误,提示该服务依赖Scoped服务,无法从根提供者解析。

代码示例

服务注册代码

services.AddScoped<ScopedServiceA>();

services.AddSingleton<SingletonA>(serviceprovider => 
    return serviceprovider.GetRequiredService<TransientServiceA>(););

services.AddSingleton<SingletonB>(serviceprovider => 
    return serviceprovider.GetRequiredService<TransientServiceA>(););

services.AddTransient<TransientServiceA>();

TransientServiceA构造函数

public TransientServiceA(ScopedServiceA scopedSrv) { ... }

错误信息

Cannot resolve 'TransientServiceA' from root provider because it requires scoped service


问题原因与解决方案

核心原因

ASP.NET Core的DI容器中,根服务提供者不允许解析依赖Scoped服务的对象——Scoped服务的生命周期绑定在特定作用域(比如请求作用域)内,根提供者没有对应的作用域上下文。

仅注册一个单例时能正常工作,是因为DI容器的延迟初始化特性:

  • 若只注册SingletonA,且应用启动阶段未主动解析该单例,它会直到第一次被使用时才初始化。如果第一次使用发生在请求作用域内(比如Controller构造函数注入SingletonA),此时会用请求作用域的服务提供者解析TransientServiceA,而请求作用域包含Scoped服务上下文,因此能正常解析。
  • 同时注册两个单例时,DI容器会在启动阶段对单例做提前验证或初始化,此时使用根服务提供者,解析TransientServiceA时发现其依赖Scoped服务,直接抛出异常。

解决方案

方案1:延迟获取Transient服务

不在单例初始化阶段直接获取TransientServiceA,而是注入IServiceProvider,在需要使用时确保在有效作用域内获取:

// 注册SingletonA
services.AddSingleton<SingletonA>(serviceprovider => 
    new SingletonA(serviceprovider));

// SingletonA实现
public class SingletonA
{
    private readonly IServiceProvider _serviceProvider;

    public SingletonA(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public void Execute()
    {
        // 创建新作用域或使用当前请求作用域获取服务
        using (var scope = _serviceProvider.CreateScope())
        {
            var transientSrv = scope.ServiceProvider.GetRequiredService<TransientServiceA>();
            // 执行业务逻辑
        }
    }
}

按同样方式修改SingletonB的注册与实现,确保每次获取TransientServiceA时都处于有效作用域内,能正确解析Scoped依赖。

方案2:调整服务生命周期(谨慎使用)

如果业务场景允许,可将ScopedServiceA改为Transient生命周期,这样TransientServiceA不再依赖Scoped服务,根提供者可直接解析。但该改动会改变服务的生命周期行为,可能引发业务逻辑问题,需结合实际场景评估。


内容的提问来源于stack exchange,提问作者Vorasoda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:03:11