使用反射处理只读列表:如何清空标记HideAttribute的只读List属性
解决不可写List类型属性的清空问题
针对你遇到的不可写List属性需要清空的需求,这里有两个实用的方案可以实现:
方案一:利用非泛型IList接口(推荐)
因为所有List<T>都实现了非泛型的IList接口,而这个接口提供了Clear()方法,我们可以通过类型转换来调用它,代码简洁高效:
protected void Remove<T>(T someData) { foreach (var property in typeof(T).GetProperties()) { // 注意:原代码这里少了括号,需要修正 if (property.GetCustomAttribute<HideAttribute>() == null) continue; Type t = property.PropertyType; if (property.CanWrite) { property.SetValue(someData, null); // 原代码这里少了分号,需要修正 } else if (property.CanRead && t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>)) { // 将属性值转换为IList,调用Clear清空 var list = property.GetValue(someData) as IList; list?.Clear(); } } }
这个方案的优势是不需要额外的反射操作,直接利用已有接口,性能和可读性都更好。
方案二:通过反射调用List<T>的Clear方法
如果你不想依赖非泛型接口,可以直接通过反射获取List<T>的Clear方法并调用:
protected void Remove<T>(T someData) { foreach (var property in typeof(T).GetProperties()) { if (property.GetCustomAttribute<HideAttribute>() == null) continue; Type t = property.PropertyType; if (property.CanWrite) { property.SetValue(someData, null); } else if (property.CanRead && t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>)) { var listInstance = property.GetValue(someData); if (listInstance == null) continue; // 获取List<T>的Clear方法 var clearMethod = t.GetMethod("Clear", Type.EmptyTypes); clearMethod?.Invoke(listInstance, null); } } }
这个方案更直接针对List<T>类型,但相比方案一多了一步反射调用方法的操作,性能略低一点。
另外提醒下你原代码里的两个小问题:
property.GetCustomAttribute<HideAttribute>需要加上括号,变成property.GetCustomAttribute<HideAttribute>()才能正确调用方法property.SetValue(someData,null)末尾缺少分号,需要补上
内容的提问来源于stack exchange,提问作者Ole Albers
相关产品推荐
相关产品推荐

