运行时获取泛型抽象BaseApplicationDbContext实例:Handler获取返回null
问题根源
你注册的ApplicationDbContext是BaseApplicationDbContext<Entity>的实现,但尝试获取的是BaseApplicationDbContext<BaseEntity>。C#泛型类默认是不变类型,DI容器无法将BaseApplicationDbContext<Entity>隐式转换为BaseApplicationDbContext<BaseEntity>,所以调用GetService会返回null。
解决办法
有三种实用方案可选:
方案1:注册时显式绑定泛型抽象类
在Program.cs的DI注册代码里,除了注册具体的ApplicationDbContext,额外添加一行将它绑定到BaseApplicationDbContext<BaseEntity>:
builder.Services.AddDbContext<ApplicationDbContext>(options => { // 这里填你的DbContext配置,比如连接字符串 options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")); }); // 显式注册抽象泛型类型,指向已注册的具体DbContext实例 builder.Services.AddScoped<BaseApplicationDbContext<BaseEntity>>(sp => sp.GetRequiredService<ApplicationDbContext>());
之后在Handler里调用scope.ServiceProvider.GetService<BaseApplicationDbContext<BaseEntity>>()就能拿到实例了。
方案2:给泛型抽象类添加协变支持(适合只读场景)
如果你的BaseApplicationDbContext<TEntity>主要做读取操作,或者TEntity只作为输出类型,可以通过协变接口实现:
- 先定义一个协变接口:
public interface IBaseApplicationDbContext<out TEntity> where TEntity : BaseEntity { // 定义你需要的DbContext操作,比如DbSet DbSet<TEntity> Entities { get; } }
- 修改抽象类实现这个接口:
public abstract class BaseApplicationDbContext<TEntity> : DbContext, IBaseApplicationDbContext<TEntity> where TEntity : BaseEntity { public DbSet<TEntity> Entities { get; set; } // 保留原有其他代码 }
- 注册时绑定协变接口:
builder.Services.AddDbContext<ApplicationDbContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")); }); builder.Services.AddScoped<IBaseApplicationDbContext<BaseEntity>>(sp => sp.GetRequiredService<ApplicationDbContext>());
之后在Handler里获取IBaseApplicationDbContext<BaseEntity>即可。
方案3:直接获取具体DbContext类型(最简单)
如果你的Handler不需要依赖抽象泛型类,直接获取具体的ApplicationDbContext是最省事的:
var dbContext = scope.ServiceProvider.GetService<ApplicationDbContext>();
内容的提问来源于stack exchange,提问作者ASantos
相关产品推荐
相关产品推荐

