初始化IL中的​​大量数据

时间:2014-01-07 21:19:11

标签: .net il

我编写了一个使用System.Reflection.Emit生成IL的编译器。这适用于代码,但我不知道如何发出我需要包含的大型初始化表。编译器的重点是生成这些表,并且无法在运行时计算初始化器。

我尝试将初始化数据存储在使用Ldstr加载的字符串中,但事实证明这些字符串总共有多长时间存在硬限制。

我还尝试发出分配数组然后分配初始化程序的代码(a [0] = const0; a [1] = const1; a [2] = const2,...)。虽然只在初始化时执行一次,但这似乎可以减慢执行速度。我猜JIT编译器不像很多线性代码。

我想我可以尝试将初始化程序包含为资源文件,但我想解析它不会那么快。理想情况下,我想使用一些方法让我将所有内容存储在一个DLL中。

在.net中初始化大量数据的“常用”方法是什么?

1 个答案:

答案 0 :(得分:3)

看看C#如何初始化值类型的静态数组。 (这可能只适用于valuetypes)。 IT在<module>所在的 - 命名空间中创建了一个类,称为<PrivateImplementationDetails>{GUID_OF_YOUR_ASSEMBLY}

在这个类中,它创建了一个结构,用于使用以下属性初始化数组:

[StructLayout(LayoutKind.Explicit, Size=SIZE_OF_ARRAY_IN_BYTES, Pack=1)]
private struct __StaticArrayInitTypeSize=SIZE_OF_ARRAY_IN_BYTES
{
}

其中SIZE_OF_ARRAY_IN_BYTES是元素的字节数乘以数组的长度。 (例如int[] foo={0,1,2,3,4,5,6,7,8,9}将是Size = 40)

在程序集中,它将数组的二进制表示形式分配给<PrivateImplementationDetails>中的内部静态只读字段。

最后,它将一个运行时场句柄加载到包含数组主体的字段,并调用方法System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray

不幸的是,关于这种方法的文档非常糟糕。看起来你将数组传递给它,然后将句柄传递给一个字段。我的示例静态初始化程序的IL看起来像这样,希望这有助于::

.method private hidebysig specialname rtspecialname static void .cctor() cil managed
{
    .maxstack 8
    L_0000: ldc.i4.s 0x15
    L_0002: newarr int32
    L_0007: dup 
    L_0008: ldtoken valuetype <PrivateImplementationDetails>{D28836D0-542D-4735-8815-954F79B1D29C}/__StaticArrayInitTypeSize=84 <PrivateImplementationDetails>{D28836D0-542D-4735-8815-954F79B1D29C}::$$method0x6000003-1
    L_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
    L_0012: stsfld int32[] Test.Program::vals
    L_0017: ret 
}