如何通过反射访问派生类型的List属性并调用其重写方法?
问题解决:将List转为可调用BaseClass方法的集合
问题原因
List<T>是不变泛型类型,即便DerivedClass继承自BaseClass,List<DerivedClass>也无法直接转换为List<BaseClass>,因此val as List<BaseClass>会返回null。而IEnumerable<out T>是协变泛型接口(带有out关键字),支持从IEnumerable<DerivedClass>到IEnumerable<BaseClass>的转换。
解决方案
以下是几种可行的实现方式:
方式1:通过IEnumerable<BaseClass>遍历调用
直接将集合转换为支持协变的IEnumerable<BaseClass>,然后遍历执行方法:
var val = prop.GetValue(obj); if (val is IEnumerable<BaseClass> items) { foreach (var item in items) { item.DoThing(); } }
方式2:使用Cast<BaseClass>转换元素
通过LINQ的Cast方法将集合中的每个元素转换为BaseClass类型:
var val = prop.GetValue(obj); var items = (val as IEnumerable)?.Cast<BaseClass>(); if (items != null) { foreach (var item in items) { item.DoThing(); } }
方式3:反射遍历集合元素(兼容非泛型场景)
如果需要处理更通用的集合类型(比如非泛型ICollection),可以通过反射获取元素并调用方法:
var val = prop.GetValue(obj); if (val is IEnumerable collection) { foreach (var item in collection) { if (item is BaseClass baseObj) { baseObj.DoThing(); } } }
完整修正后的代码示例
var pt = prop.PropertyType; if (pt.IsGeneric && (pt.GetGenericTypeDefinition() == typeof(List<>)) && (pt.GetGenericArguments()[0].IsSubclassOf(typeof(BaseClass)))) { var val = prop.GetValue(obj); if (val is IEnumerable<BaseClass> items) { foreach (var item in items) { item.DoThing(); } } }
内容的提问来源于stack exchange,提问作者Anton Zhuchkov
相关产品推荐
相关产品推荐

