如何通过反射获取类的List<>属性并统计列表元素个数?
实现方案
PropertyInfo.GetValue()读取普通实例属性时参数规则很明确:
- 第一个参数传入要读取属性所属的对象实例,对应你代码里的
argsItem - 第二个参数是索引属性专用的索引值数组,普通非索引属性直接传
null即可
首先是修正后可直接运行的代码:
// 需要引入System.Collections命名空间使用IList接口 using System.Collections; using System.Reflection; int NumberOfItems<TItem>(TItem argsItem) { if (argsItem == null) throw new ArgumentNullException(nameof(argsItem)); // 获取指定名称的属性元数据,属性名可根据实际场景替换 PropertyInfo listProperty = argsItem.GetType().GetProperty("DetailsList"); if (listProperty == null) throw new ArgumentException("传入对象不存在名为DetailsList的公共属性"); // 读取属性值:第一个参数传当前实例,普通属性第二个参数传null object propertyValue = listProperty.GetValue(argsItem, null); // 校验属性值合法性:所有泛型List<T>都实现了非泛型IList接口,可直接转换 if (propertyValue is not IList detailsList) throw new InvalidOperationException("目标属性值为null,或不是List集合类型"); return detailsList.Count; }
适配多属性名场景的优化
如果你的业务中不同类的List属性名不固定(比如有的叫DetailsList,有的叫Items,有的叫OrderLines),不需要硬编码属性名,可以写通用逻辑自动扫描类型下所有泛型List属性:
using System.Collections; using System.Reflection; int CountGenericListItems<TItem>(TItem argsItem) { if (argsItem == null) throw new ArgumentNullException(nameof(argsItem)); Type targetType = argsItem.GetType(); // 查找类型中第一个公共实例泛型List属性 PropertyInfo? listProp = targetType.GetProperties() .FirstOrDefault(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(List<>)); if (listProp == null) throw new ArgumentException("传入对象类型不存在公共的List<T>类型属性"); if (listProp.GetValue(argsItem, null) is not IList listInstance) throw new InvalidOperationException("List属性未赋值(为null),无法统计元素数量"); return listInstance.Count; }
关键注意点
- 读取静态属性时,
GetValue第一个参数直接传null即可,不需要传实例 - 只有读取索引器属性(比如定义了
public object this[int index]的属性)时,才需要给第二个参数传入索引值数组,普通属性统一传null - 不需要反射解析List的泛型参数类型,所有
List<T>都实现了非泛型IList接口,直接转成IList就能读取Count属性,性能更好代码也更简洁 - 一定要加空值校验,避免List属性没初始化赋值时触发空引用异常
内容的提问来源于stack exchange,提问作者Elshad Shabanov
相关产品推荐
相关产品推荐

