Take a look at how C# initializes static arrays of value-types. (This might only work with valuetypes).
IT creates a class in the - namespace where <module>
is located, called <PrivateImplementationDetails>{GUID_OF_YOUR_ASSEMBLY}
In this class it creates a struct to initialize the array using the attribute:
[StructLayout(LayoutKind.Explicit, Size=SIZE_OF_ARRAY_IN_BYTES, Pack=1)]
private struct __StaticArrayInitTypeSize=SIZE_OF_ARRAY_IN_BYTES
{
}
Where SIZE_OF_ARRAY_IN_BYTES is the number of bytes for the element times the length of the array. (e.g. int[] foo={0,1,2,3,4,5,6,7,8,9}
will be Size=40)
in the assembly it assigns the binary representation of the array to a internal static readonly field in <PrivateImplementationDetails>
.
Finally, it loads a runtimefield handle to the field holding the arrays body, and calls the method System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray
Unfortunately, the documentation on this method is awful. It looks like you pass it the array and then pass it the handle to a field. The IL for my example static initializer looks like this, hope this helps::
.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
}