如何从基类实例化派生类中DbSet类型的指定属性
自动实例化派生类DbSet属性的实现方案
这问题我之前也碰到过,用反射就能完美解决!直接在基类的构造函数里自动遍历并实例化派生类中所有DbSet类型的属性,再也不用在每个派生类里手动写初始化代码了。
完整实现代码
首先是修改后的基类TBaseModel:
using System.Reflection; using System.Linq; public class TBaseModel { public TBaseModel() { // 获取当前实例的实际类型(也就是派生类的类型) var derivedType = GetType(); // 筛选出所有公开的、实例级的DbSet类型属性(包括泛型DbSet<T>) var dbSetProperties = derivedType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.PropertyType == typeof(DbSet) || (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))); foreach (var prop in dbSetProperties) { // 创建DbSet实例:泛型用Activator处理,非泛型直接new var dbSetInstance = prop.PropertyType.IsGenericType ? Activator.CreateInstance(prop.PropertyType) : new DbSet(); // 给当前实例的对应属性赋值 prop.SetValue(this, dbSetInstance); } } }
然后是派生类TDataModel,现在完全不用手动初始化属性了:
public class TDataModel : TBaseModel { public DbSet Cars { get; set; } // 泛型DbSet也能自动处理 public DbSet<Order> Orders { get; set; } public TDataModel() { // 这里啥都不用写!基类构造会自动搞定所有DbSet的实例化 } }
关键逻辑说明
- 获取派生类类型:用
GetType()而不是typeof(TBaseModel),因为在基类构造函数里,this指向的是派生类的实例,所以能拿到正确的派生类类型信息。 - 筛选DbSet属性:通过反射筛选出类型为
DbSet或者泛型定义为DbSet<>的属性,覆盖了常见的两种DbSet使用场景。 - 实例化与赋值:用
Activator.CreateInstance统一处理泛型和非泛型的DbSet实例创建,然后通过PropertyInfo.SetValue给属性赋值。
注意事项
- 确保你的
DbSet类有公开的无参构造函数,否则Activator.CreateInstance会抛出异常。如果需要参数化构造,可以根据需求修改代码,传入对应的构造参数。 - 反射确实会有一点点性能开销,但对于数据模型这种初始化次数极少的场景,这个开销几乎可以忽略不计。
- 如果后续要添加新的DbSet属性到派生类里,完全不用改构造函数,基类会自动处理新属性的实例化。
内容的提问来源于stack exchange,提问作者Realbitt
相关产品推荐
相关产品推荐

