C#反射获取继承泛型基类私有字段值时报ArgumentException
错误根因
你遇到的ArgumentException本质是继承链遍历逻辑存在类型元数据错配问题:
- 现有向上遍历逻辑中,只要检测到当前类型是泛型,就直接把遍历用的
type变量替换为开放泛型定义(也就是DebugProperty<>) - 从开放泛型定义上获取到的
m_value元数据,是绑定在未指定类型参数的泛型模板上的,和你实际持有的Bool实例对应的封闭泛型元数据不兼容 - 此时调用
GetValue时,运行时会校验FieldInfo绑定的声明类型和传入实例的类型是否兼容,自然抛出参数不匹配的异常
正确实现方案
修正核心逻辑:遍历继承链时始终沿着实际的封闭类型层级向上查找,只在做类型判断时临时对比泛型定义,绝对不替换遍历用的类型变量。
修正后可直接运行的代码示例:
FieldInfo field = owner.GetType().GetField( name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic ); // 提前获取字段对应的实例引用,避免重复取值 object fieldInstance = field.GetValue(owner); Type type = field.FieldType; // 沿实际继承链向上匹配基类 while (type != null) { // 仅做判断时提取泛型定义对比,不修改遍历的type本身 if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(DebugProperty<>)) { break; } type = type.BaseType; } // 此时type已经是实际的DebugProperty<bool>封闭泛型类型 FieldInfo m_value = type.GetField( "m_value", BindingFlags.Instance | BindingFlags.NonPublic ); object val = m_value.GetValue(fieldInstance).ToString();
关键注意点
- 之前针对直接用
DebugProperty<bool>声明的字段能正常取值,是因为该场景下根本不需要向上遍历,直接从字段本身的封闭泛型类型上获取的FieldInfo天然和实例匹配,不会出现元数据错配 - 反射操作中,从开放泛型定义获取的FieldInfo、MethodInfo等元数据,不能直接用来操作任何具体的封闭泛型实例,必须绑定到实际的封闭泛型类型上才能正常调用
内容的提问来源于stack exchange,提问作者Rotary Heart
相关产品推荐
相关产品推荐

