.NET Core MVC 6中如何在先注册的DbContext中注入后注册的服务?
解决方案
你遇到的是循环依赖+服务注册顺序的问题,核心是通过IServiceProvider延迟获取服务,绕过直接注入带来的循环依赖,同时满足SaveChangesAsync中使用AccountService的需求。
具体实现步骤
1. 修改MyDbContext,注入IServiceProvider
在MyDbContext的构造函数中注入IServiceProvider,通过它在SaveChangesAsync中延迟获取IAccountService实例,避免直接注入导致的循环依赖:
public class MyDbContext : DbContext { private readonly IServiceProvider _serviceProvider; // 构造函数注入DbContext配置和IServiceProvider public MyDbContext(DbContextOptions<MyDbContext> options, IServiceProvider serviceProvider) : base(options) { _serviceProvider = serviceProvider; } public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) { // 从当前作用域中获取IAccountService实例 var accountService = _serviceProvider.GetRequiredService<IAccountService>(); // 在这里使用AccountService的功能,比如获取当前用户信息 // var currentUser = accountService.GetCurrentUserId(); // 执行原有的保存逻辑 return await base.SaveChangesAsync(cancellationToken); } }
2. 保持原有服务注册顺序
无需调整MyDbContext和IAccountService的注册顺序,因为我们是通过IServiceProvider延迟获取服务,只要IAccountService已注册即可:
builder.Services.AddDbContext<MyDbContext>(); // 其他服务注册... builder.Services.AddScoped<IAccountService, AccountService>();
3. AccountService的依赖注入保持不变
AccountService仍然可以正常注入MyDbContext,因为当AccountService被创建时,当前作用域的MyDbContext已经存在:
public class AccountService : IAccountService { private readonly MyDbContext _dbContext; public AccountService(MyDbContext dbContext) { _dbContext = dbContext; } // 实现IAccountService的方法... }
关键原理说明
IServiceProvider是.NET依赖注入的核心服务,注入到MyDbContext后,它可以在SaveChangesAsync执行时,从当前Scoped作用域中获取已注册的IAccountService实例,避开了直接注入导致的循环依赖。- 因为
MyDbContext和IAccountService都是Scoped生命周期,所以在同一个请求作用域内,两者的实例是匹配的,不会出现服务不兼容的问题。
内容的提问来源于stack exchange,提问作者SuperNev
相关产品推荐
相关产品推荐

