使用反射调用PropertyInfo.GetValue获取未知类型对象列表的正确语法
解决未知类型列表的PropertyInfo.GetValue处理问题
嘿,我来帮你搞定这个获取未知类型列表的问题!你现在的卡点在于不知道列表的具体泛型类型,没法直接强转成特定的List<T>,其实我们可以借助.NET的非泛型IEnumerable接口来统一处理——毕竟所有列表/集合类型都实现了这个接口。
首先,先修正你代码里的列表处理部分,完整的实现思路是这样的:
- 先用
GetValue获取到属性的实例对象,注意第二个参数传null(因为这是实例属性,静态属性才需要传其他值)。 - 排除掉
string类型(因为string也实现了IEnumerable<char>,但我们要处理的是真正的列表集合,不是字符串)。 - 将获取到的对象转为
IEnumerable,遍历每个元素,对每个元素调用你的Validate方法收集错误。
下面是修改后的完整代码:
public IEnumerable<Error> FindErrors(object obj) { var errors = new List<Error>(); errors.AddRange(Validate(obj)); List<PropertyInfo> properties = obj.GetType().GetProperties().Where(p => !p.PropertyType.IsByRef).ToList(); foreach (var p in properties) { if (IsList(p)) { // 获取列表属性的实例 var listInstance = p.GetValue(obj, null); // 排除string,同时确保实例不为null且是IEnumerable if (listInstance != null && listInstance is IEnumerable enumerable && listInstance.GetType() != typeof(string)) { foreach (var item in enumerable) { // 递归验证列表中的每个元素 errors.AddRange(FindErrors(item)); } } } } return errors; } // 补充IsList方法的参考实现(如果你还没写的话) private bool IsList(PropertyInfo p) { var propertyType = p.PropertyType; // 兼容泛型List和其他实现IEnumerable的集合类型,同时排除string return (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>)) || (typeof(IEnumerable).IsAssignableFrom(propertyType) && propertyType != typeof(string)); }
关键细节说明:
p.GetValue(obj, null):这是获取实例属性值的标准写法,第二个参数用于索引器属性(比如数组的索引),普通列表属性传null即可。- 排除
string:因为字符串会被误判为IEnumerable<char>,但我们不需要验证字符串的每个字符,所以要单独排除。 - 递归调用
FindErrors(item):这样不仅能验证列表本身,还能深入验证列表里每个对象的属性,符合你整体的错误查找逻辑。
如果你的IsList方法原本只判断泛型List<>,建议改成上面的版本,这样能兼容更多集合类型(比如HashSet<T>、ObservableCollection<T>等);当然如果你只需要处理List<>,保持原来的判断逻辑也完全没问题。
内容的提问来源于stack exchange,提问作者ashlar64
相关产品推荐
相关产品推荐

