.NET Core控制台应用中AddScoped与AddSingleton的区别
在控制台应用中AddScoped与AddSingleton的行为差异
在控制台这类没有默认请求上下文的应用里,AddScoped和AddSingleton的核心差异体现在生命周期触发方式、实例复用范围、资源释放时机三个方面:
1. 生命周期触发与实例创建规则
- AddSingleton:第一次从服务容器获取实例时创建,之后整个应用生命周期内复用同一个实例,不管从根容器还是子作用域获取,拿到的都是同一个对象。
- AddScoped:必须手动创建
IServiceScope(通过serviceProvider.CreateScope())才能获取合规的实例。如果直接从根容器获取Scoped服务,会触发.NET的警告,且实例会绑定到根容器的生命周期(等同于Singleton)——这是反模式,容易引发资源泄漏问题,绝不推荐。
2. 实例复用范围
- AddSingleton:全局唯一,所有代码路径获取的都是同一个实例,哪怕跨多个手动创建的作用域。
- AddScoped:仅在单个手动创建的作用域内复用。不同作用域中获取的Scoped服务是完全独立的实例。
3. 资源释放时机
- AddSingleton:只有当应用程序关闭、根服务容器被释放时,才会销毁实现了
IDisposable的Singleton实例。 - AddScoped:当调用
scope.Dispose()(通常通过using语句自动执行)时,该作用域内所有Scoped实例都会被立即释放,无需等待应用关闭,适合管理需要及时回收的资源。
代码示例
// 注册服务 var services = new ServiceCollection(); services.AddScoped<SomeServiceClass>(); services.AddSingleton<AnotherServiceClass>(); var provider = services.BuildServiceProvider(); // 测试Scoped服务:同一作用域内实例复用 using (var scope = provider.CreateScope()) { var scoped1 = scope.ServiceProvider.GetRequiredService<SomeServiceClass>(); var scoped2 = scope.ServiceProvider.GetRequiredService<SomeServiceClass>(); Console.WriteLine(scoped1.GetHashCode() == scoped2.GetHashCode()); // 输出 True } // 不同作用域的Scoped实例独立 using (var anotherScope = provider.CreateScope()) { var scoped3 = anotherScope.ServiceProvider.GetRequiredService<SomeServiceClass>(); Console.WriteLine(scoped3.GetHashCode() != scoped1.GetHashCode()); // 输出 True } // 测试Singleton服务:全局复用 var singleton1 = provider.GetRequiredService<AnotherServiceClass>(); var singleton2 = provider.GetRequiredService<AnotherServiceClass>(); Console.WriteLine(singleton1.GetHashCode() == singleton2.GetHashCode()); // 输出 True
内容的提问来源于stack exchange,提问作者Subin Jacob
相关产品推荐
相关产品推荐

