C#如何对FieldInfo.GetValue返回的对象进行动态类型转换
解决方案
你期望的运行时动态类型强转语法C#不支持,强转目标类型必须在编译期确定,可通过以下三种方案实现同等效果:
方案1:定义公共接口/抽象基类(最推荐,编译期类型安全)
所有BoolEventProperty/FloatEventProperty/IntEventProperty均包含Value成员,你可以先定义公共非泛型接口,让所有属性类实现该接口:
// 定义公共接口 public interface IEventProperty { object Value { get; } } // 各个属性类实现接口示例 public class BoolEventProperty : IEventProperty { public bool Value { get; set; } object IEventProperty.Value => Value; } // FloatEventProperty、IntEventProperty同理实现IEventProperty接口即可
遍历逻辑可直接简化为:
foreach (var v in typeof(CentralParams).GetFields()) { var fieldValue = v.GetValue(_centralParams); if (fieldValue is IEventProperty prop) { print($"{v.Name} {prop.Value}"); } }
该方案编译期即可完成类型校验,不会出现运行时成员不存在的问题,后续新增属性类型只要实现IEventProperty即可自动适配,无需修改遍历逻辑。
方案2:使用dynamic关键字(实现最简单,适合确定所有字段都有Value成员的场景)
C#的dynamic类型会在运行时解析成员,不需要编译期确定类型,直接改写遍历逻辑即可:
foreach (var v in typeof(CentralParams).GetFields()) { dynamic prop = v.GetValue(_centralParams); try { print($"{v.Name} {prop.Value}"); } catch (RuntimeBinderException) { // 可在此处处理字段无Value成员的异常情况 } }
注意:如果字段值不存在Value成员,会抛出运行时异常,建议加异常捕获做兼容。
方案3:反射读取Value属性(无侵入,不需要修改原有属性类定义)
如果不能修改XXXEventProperty的定义,也不想用dynamic,可以直接通过反射读取Value属性:
foreach (var v in typeof(CentralParams).GetFields()) { var fieldValue = v.GetValue(_centralParams); var valueProp = fieldValue.GetType().GetProperty("Value"); if (valueProp != null) { var value = valueProp.GetValue(fieldValue); print($"{v.Name} {value}"); } }
该方案不需要修改原有类的代码,适配性最强,性能略低于前两种方案,常规遍历场景下感知不到差异。
内容的提问来源于stack exchange,提问作者arcadeperfect
相关产品推荐
相关产品推荐

