基于System.Reflection.Emit生成子类方法时无法访问基类readonly字段
解决Reflection.Emit子类访问基类readonly字段的问题
嘿,这个问题我之前折腾Reflection.Emit的时候也碰到过,核心就是要正确获取基类字段的引用,再配合正确的IL指令来访问。咱们一步步来解决:
第一步:正确获取基类的readonly字段引用
你的BaseClass里的field是默认私有(没有访问修饰符)的readonly实例字段,所以必须用正确的BindingFlags才能通过反射拿到它的FieldInfo:
// 获取基类的field字段 FieldInfo baseField = typeof(BaseClass).GetField( "field", BindingFlags.Instance | BindingFlags.NonPublic ); // 校验是否获取成功,避免后续出错 if (baseField == null) { throw new InvalidOperationException("无法找到基类的field字段,请检查字段名称和BindingFlags是否正确"); }
第二步:生成IL代码访问字段
在你定义的子类方法里,需要通过IL指令加载当前实例(this),再加载基类的字段值。以下是完整的示例代码:
// 假设你已经创建了继承自BaseClass的TypeBuilder MethodBuilder methB = typeBuilder.DefineMethod( "GetBaseField", // 方法名称 MethodAttributes.Public, CallingConventions.HasThis, typeof(string), // 返回类型 new Type[] { typeof(object) } // 参数列表,这里和你给出的一致 ); ILGenerator il = methB.GetILGenerator(); // 1. 加载当前实例(this)到栈顶:实例方法的第一个参数是this,对应Ldarg_0 il.Emit(OpCodes.Ldarg_0); // 2. 加载基类的field字段值到栈顶 il.Emit(OpCodes.Ldfld, baseField); // 3. 返回栈顶的字符串(匹配方法的返回类型) il.Emit(OpCodes.Ret);
关键注意点
- 千万别用错IL指令:要用
Ldfld(加载实例字段),而不是Ldsfld(加载静态字段),因为field是实例字段 - 必须加载
this实例:因为字段是实例级别的,没有this引用就没法访问实例字段 - 反射访问私有字段的权限:默认情况下,Reflection.Emit生成的代码可以访问基类的私有字段,只要你正确拿到了
FieldInfo
这样生成的子类方法就能正常返回基类field的值啦。
内容的提问来源于stack exchange,提问作者chriptus13
相关产品推荐
相关产品推荐

