我正在尝试使用 Reflection.Emit (在 c# 中)创建一个新类型。
我想要创建的代码类似于
public class
{
public static int[] A = new int[] {1, 2, 3};
}
我首先尝试定义一个字段,然后设置它的值:
var fb = tb.DefineField("A", FieldAttributes.Public | FieldAttributes.Static);
fb.SetValue(null, new int[] {1, 2, 3});
但它不起作用,因为 setValue 仅支持简单类型(int,float,...)。
现在我尝试使用 DefineInitializedData (更长的代码不起作用...),但它不会生成任何有效的 IL 代码。
setValue 仅支持简单类型(int、float、...)
不,这不对。FieldBuilder
继承SetValue()
from FieldInfo
,但这没有意义FieldBuilder
.
有FieldBuilder.SetConstant() https://msdn.microsoft.com/en-us/library/system.reflection.emit.fieldbuilder.setconstant,但它只适用于const
字段。而你不能拥有const
引用类型的字段的值不是null
.
您需要做的事情与任何编译器都必须做的事情相同:创建一个静态构造函数,在那里创建数组,然后将其分配给该字段:
var fb = tb.DefineField("A", typeof(int[]), FieldAttributes.Public | FieldAttributes.Static);
var ctor = tb.DefineTypeInitializer();
var il = ctor.GetILGenerator();
// new int[3]
il.Emit(OpCodes.Ldc_I4_3);
il.Emit(OpCodes.Newarr, typeof(int));
// array[0] = 1
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Stelem_I4);
// array[1] = 2
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Ldc_I4_2);
il.Emit(OpCodes.Stelem_I4);
// arr[2] = 3
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldc_I4_2);
il.Emit(OpCodes.Ldc_I4_3);
il.Emit(OpCodes.Stelem_I4);
// A = array
il.Emit(OpCodes.Stsfld, fb);
il.Emit(OpCodes.Ret);
如果您查看 C# 编译器生成的反编译代码,您可能会看到不同的 IL,使用类似<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12
and RuntimeHelpers.InitializeArray() https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.initializearray。这是一种优化,我认为如果您手动编写 IL,那么使用我上面展示的常规方法会更简单。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)