.NET Core 2类库中如何手动控制依赖注入Scoped作用域?
手动管理.NET Core 2.0类库中的Scoped作用域
嘿,针对你在非ASP.NET Core的.NET Core 2.0类库中手动启动和结束Scoped作用域的需求,其实完全可以借助原生DI的IServiceScope来实现,特别适合你说的复杂测试场景,下面我给你一步步捋清楚:
1. 先构建你的服务容器
首先得完成服务注册并构建出ServiceProvider,这是DI功能的基础:
// 初始化服务集合 var services = new ServiceCollection(); // 注册Scoped生命周期的服务 services.AddScoped<IMyScopedService, MyScopedService>(); // 按需添加其他生命周期的服务 services.AddSingleton<IMySingletonService, MySingletonService>(); services.AddTransient<IMyTransientService, MyTransientService>(); // 构建服务提供者 var serviceProvider = services.BuildServiceProvider();
2. 创建并使用Scoped作用域
核心是调用serviceProvider.CreateScope()方法创建作用域,这个方法返回的IServiceScope实现了IDisposable——强烈推荐用using块包裹,这样作用域会在代码块结束时自动释放,里面的Scoped服务也会被自动清理(如果服务实现了IDisposable):
using (var scope = serviceProvider.CreateScope()) { var scopeServiceProvider = scope.ServiceProvider; // 从当前作用域解析Scoped服务 var scopedService = scopeServiceProvider.GetRequiredService<IMyScopedService>(); // 同一个作用域内多次解析,得到的是同一个实例 var sameScopedService = scopeServiceProvider.GetRequiredService<IMyScopedService>(); Debug.Assert(scopedService == sameScopedService); // 在这里执行你的业务逻辑或者测试代码 scopedService.DoSomething(); } // 作用域在这里被自动释放,Scoped服务的Dispose方法会被调用(如果有的话)
3. 手动控制作用域(特殊场景可用)
如果因为某些原因不想用using,也可以手动调用Dispose()结束作用域,但一定要记得调用,否则会造成资源泄漏:
var scope = serviceProvider.CreateScope(); try { var scopedService = scope.ServiceProvider.GetRequiredService<IMyScopedService>(); // 执行你的操作 } finally { // 手动释放作用域 scope.Dispose(); }
4. 测试场景的最佳实践
在复杂测试中,建议给每个测试方法单独创建一个作用域,这样每个测试都能拿到独立的Scoped服务实例,彻底避免测试之间的状态污染:
[Test] public void MyTest() { // 服务容器构建可以放到TestInitialize方法中,避免重复代码 var services = new ServiceCollection(); services.AddScoped<IMyScopedService, MyScopedService>(); var serviceProvider = services.BuildServiceProvider(); // 为当前测试创建独立作用域 using (var scope = serviceProvider.CreateScope()) { var scopedService = scope.ServiceProvider.GetRequiredService<IMyScopedService>(); // 执行测试断言 Assert.IsNotNull(scopedService); } }
内容的提问来源于stack exchange,提问作者k.c.
相关产品推荐
相关产品推荐

