使用Microsoft.Extensions.DependencyInjection时,WPF中AddScoped与AddSingleton有何差异?
在WPF/控制台应用中使用Microsoft.Extensions.DependencyInjection时AddScoped与AddSingleton的差异
核心本质差异
AddSingleton:注册的服务实例是全局单例——整个应用运行期间只会被创建一次,无论从哪个服务提供者获取,拿到的都是同一个实例,直到应用退出才会被销毁。
比如你代码里两次写services.AddSingleton<MainViewModel>(),实际没有任何差异:DI容器只会保留最后一次的注册条目,但最终生成的实例仍然是全局唯一的。AddScoped:服务实例的生命周期绑定到服务作用域(IServiceScope)。在Web应用中,每个HTTP请求会自动创建一个作用域,所以Scoped服务在单个请求内是单例;但在WPF/控制台这类没有自动请求作用域的场景下:
- 如果直接从根服务提供者(也就是你代码里
serviceProvider.GetService<MainWindow>()这种方式)获取Scoped服务,根提供者本身相当于一个全局作用域,此时Scoped服务的行为和Singleton完全一致——全程只有一个实例。 - 只有当你手动创建局部作用域时,Scoped的特性才会体现:
这种情况下,每个using var scope = serviceProvider.CreateScope(); var scopedWindow = scope.ServiceProvider.GetService<MainWindow>();IServiceScope内会创建唯一的Scoped服务实例,当作用域被销毁(using块结束)时,实例也会被释放。
- 如果直接从根服务提供者(也就是你代码里
结合你的代码分析
你代码里同时注册了AddSingleton<MainWindow>()和AddScoped<MainWindow>(),当调用serviceProvider.GetService<MainWindow>()时,DI容器会返回最后一次注册的服务(也就是Scoped的MainWindow)。但因为是从根服务提供者获取,这个MainWindow实例的生命周期和Singleton完全一样——整个应用只会存在一个。
实际使用场景
- 用
AddSingleton存储全局共享的状态或服务(比如配置信息、全局缓存); - 用
AddScoped处理局部生命周期的需求(比如某个业务流程内需要复用实例,流程结束后销毁资源),但必须手动创建IServiceScope才能发挥作用。
内容的提问来源于stack exchange,提问作者meJustAndrew
相关产品推荐
相关产品推荐

