泛型<T>函数无法获取继承类字段?DataTable转List反射问题
问题原因与解决方法
核心原因
你代码里调用的typeof(T).GetProperties()只能获取类的属性(Property),而FooChild中的IsFoo是字段(Field)——这是.NET反射里两个完全不同的成员类型,所以不管加什么BindingFlags,GetProperties()都不会读取字段,自然拿不到IsFoo的信息。
解决方法
方案1:将字段改为属性(推荐)
遵循.NET编码规范,把FooChild里的字段改成自动属性,原转换函数无需修改即可正常获取该成员:
public class FooChild : Foo { public bool IsFoo { get; set; } // 替换原来的public bool IsFoo; }
方案2:修改转换函数,同时支持属性和字段
如果必须保留字段,需在反射逻辑中同时获取属性和字段,统一处理映射:
public static List<T> ConvertToList<T> (DataTable dt) { List<string> columnNames = dt.Columns.Cast<DataColumn>().Select(c => c.ColumnName.ToLower()).ToList(); // 获取所有公共实例属性 var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); // 获取所有公共实例字段 var fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance); // 统一整理可赋值的成员(名称+赋值方法) var assignableMembers = new List<(string LowerName, Action<T, object> SetValue)>(); // 处理属性 foreach (var prop in properties) { string lowerName = prop.Name.ToLower(); if (columnNames.Contains(lowerName)) { assignableMembers.Add((lowerName, (obj, val) => prop.SetValue(obj, val))); } } // 处理字段 foreach (var field in fields) { string lowerName = field.Name.ToLower(); if (columnNames.Contains(lowerName)) { assignableMembers.Add((lowerName, (obj, val) => field.SetValue(obj, val))); } } // 转换DataTable到List<T>的核心逻辑 var result = new List<T>(); foreach (DataRow row in dt.Rows) { T item = Activator.CreateInstance<T>(); foreach (var member in assignableMembers) { object value = row[member.LowerName]; if (value != DBNull.Value) { member.SetValue(item, value); } } result.Add(item); } return result; }
注意事项
- 字段(Field)是类直接声明的变量,属性(Property)是封装字段的访问器(带
get/set),两者在反射中是分开处理的。 - 优先使用属性,因为它符合面向对象的封装原则,能更好地控制成员的访问逻辑。
内容的提问来源于stack exchange,提问作者Rikube
相关产品推荐
相关产品推荐

