ASP.NET Core依赖注入问题:AddScoped未创建新实例
问题分析与解决方案
你的理解完全正确——Scoped生命周期的服务在ASP.NET Core中确实应该为每个HTTP请求创建一个新实例。出现构造函数只执行一次、后续请求复用同一个实例的问题,大概率是踩了以下几个常见的依赖注入坑:
可能的原因及解决方法
1. Scoped服务被Singleton服务"劫持"了生命周期
如果你的IMyClass被注入到了一个Singleton生命周期的服务中,或者在应用启动阶段(比如ConfigureServices方法内)直接解析了IMyClass实例,那么Scoped服务会被强制提升为Singleton生命周期。因为Singleton服务的生命周期贯穿整个应用,它依赖的Scoped服务会被长期持有,不再随请求销毁。
解决办法:
- 绝对不要在
ConfigureServices里直接调用provider.GetService<IMyClass>(),这个阶段还没有请求上下文,Scoped服务会被当成Singleton处理。 - 如果必须在Singleton服务中使用Scoped服务,要通过
IServiceScopeFactory创建临时作用域,用完即销毁:public class SingletonService(IServiceScopeFactory scopeFactory) { public void DoRequestRelatedWork() { using var scope = scopeFactory.CreateScope(); var myClass = scope.ServiceProvider.GetRequiredService<IMyClass>(); // 在这里使用myClass,作用域结束后实例会被自动释放 } }
2. 注册服务时没有正确绑定请求上下文
你的注册代码里直接new MyClass("anyValue"),如果MyClass的构造函数需要基于请求信息做动态配置,你没有通过provider获取请求相关的服务(比如IHttpContextAccessor),反而在注册阶段就固定了实例的配置,导致实例被提前创建并复用。
解决办法:
- 先注册
IHttpContextAccessor(ASP.NET Core不会默认注册这个服务):services.AddHttpContextAccessor(); - 修改Scoped服务的注册逻辑,通过
provider动态获取请求上下文,再创建实例:services.AddScoped<IMyClass>(provider => { var httpContextAccessor = provider.GetRequiredService<IHttpContextAccessor>(); var httpContext = httpContextAccessor.HttpContext; if (httpContext == null) { throw new InvalidOperationException("请在HTTP请求环境中使用此服务"); } // 根据请求信息生成动态配置值,比如从Header、Query中获取 var dynamicConfig = httpContext.Request.Query["config"].ToString() ?? "defaultValue"; return new MyClass(dynamicConfig); });
3. 验证实例唯一性
为了确认问题,你可以在MyClass的构造函数里加个日志或打印HashCode,观察每个请求的输出是否不同:
public class MyClass { public MyClass(string configValue) { Console.WriteLine($"MyClass实例创建,HashCode: {GetHashCode()}, 配置值: {configValue}"); // 其他构造逻辑 } }
如果不同请求的HashCode相同,说明确实是实例被复用了,再回头检查上面的两种情况。
内容的提问来源于stack exchange,提问作者Eduardo Lanfredi
相关产品推荐
相关产品推荐

