gpt4 book ai didi

c# - Msil 以动态类型发出静态数组

转载 作者:行者123 更新时间:2023-11-30 15:26:50 27 4
gpt4 key购买 nike

我正在尝试使用 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 is only supported for simple types (int, float, ...)

不,不是。 FieldBuilder继承SetValue()来自 FieldInfo , 但对于 FieldBuilder 没有意义.

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 的东西和 RuntimeHelpers.InitializeArray() .这是一种优化,我认为如果您手动编写 IL,使用我上面展示的常规方法会更简单。

关于c# - Msil 以动态类型发出静态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28505200/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com