Blazor中调用ScopeFactory.CreateScope()时如何让指定依赖从根容器解析?
解决Blazor中OwningComponentBase作用域下无法获取根服务的问题
针对你遇到的问题——用OwningComponentBase隔离DbContext避免并发操作错误,但导致依赖的根级别服务(MyAuthState)无法正常注入的情况,这里提供几个可行的解决思路:
方案1:手动传递根服务实例
直接在组件中注入根级别的MyAuthState,同时通过OwningComponentBase获取新作用域的DbContext,手动实例化MyService并传入两个依赖:
// 组件代码 @inherits OwningComponentBase<MyDbContext> @inject MyAuthState MyAuthState @code { private MyService _myService; protected override void OnInitialized() { // 手动组合依赖:新作用域的DbContext + 根容器的MyAuthState _myService = new MyService(Context, MyAuthState); } // 组件销毁时释放资源 public override void Dispose(bool disposing) { _myService?.Dispose(); // 如果MyService实现了IDisposable base.Dispose(disposing); } }
这种方式简单直接,适合依赖较少的场景。
方案2:自定义混合作用域
如果MyService还有其他作用域依赖,可手动创建作用域,并将根服务实例注册到新作用域中,再从作用域解析MyService:
// 组件代码 @inject IServiceScopeFactory ScopeFactory @inject MyAuthState MyAuthState @code { private IServiceScope _scope; private MyService _myService; protected override void OnInitialized() { _scope = ScopeFactory.CreateScope(); var scopeServices = _scope.ServiceProvider; // 将根级的MyAuthState注册到当前作用域(覆盖默认的解析逻辑) var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(MyAuthState); // 从原作用域中获取其他需要的服务(比如DbContext) serviceCollection.AddSingleton(scopeServices.GetRequiredService<MyDbContext>()); // 注册MyService serviceCollection.AddTransient<MyService>(); var combinedProvider = serviceCollection.BuildServiceProvider(); _myService = combinedProvider.GetRequiredService<MyService>(); } public override void Dispose(bool disposing) { _scope?.Dispose(); _myService?.Dispose(); base.Dispose(disposing); } }
方案3:封装服务工厂
创建一个专门的工厂类,封装混合作用域的服务创建逻辑,让组件代码更简洁:
// 工厂类 public class MyServiceFactory { private readonly IServiceScopeFactory _scopeFactory; private readonly MyAuthState _myAuthState; public MyServiceFactory(IServiceScopeFactory scopeFactory, MyAuthState myAuthState) { _scopeFactory = scopeFactory; _myAuthState = myAuthState; } public MyService Create() { var scope = _scopeFactory.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>(); return new MyService(dbContext, _myAuthState) { // 如果需要关联作用域的生命周期,可在这里保存scope,在MyService.Dispose时释放 Scope = scope }; } } // 注册工厂(根作用域) builder.Services.AddSingleton<MyServiceFactory>(); // 组件代码 @inject MyServiceFactory ServiceFactory @code { private MyService _myService; protected override void OnInitialized() { _myService = ServiceFactory.Create(); } public override void Dispose(bool disposing) { _myService?.Dispose(); base.Dispose(disposing); } } // 可选:让MyService实现IDisposable来释放作用域 public class MyService : IDisposable { private readonly MyDbContext _ctx; private readonly MyAuthState _myAuthState; internal IServiceScope? Scope { get; set; } public MyService(MyDbContext ctx, MyAuthState myAuthState) { _ctx = ctx; _myAuthState = myAuthState; } public void Dispose() { Scope?.Dispose(); } }
内容的提问来源于stack exchange,提问作者Vlado Pandžić
相关产品推荐
相关产品推荐

