How to read array initializer values ​​from a .NET assembly

How can I read the values, say: '99' from the assembly containing this code?

using Sytem; public class Class1 { public Class1() { // array initializer, want to read '99', '100'... from assembly var a = new double[,] { { 1, 2, 3 }, { 99, 100, 101 } }; // ... } } 

What have i done so far

Method in ILDASM:

 .method /*06000001*/ public hidebysig specialname rtspecialname instance void .ctor() cil managed // SIG: 20 00 01 { // Method begins at RVA 0x2080 // Code size 29 (0x1d) .maxstack 3 .locals /*11000001*/ init ([0] float64[0...,0...] a) .language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' // Source File 'c:\Users\heini19\Documents\Visual Studio 2013\Projects\WcfService1\ClassLibrary1\Class1.cs' //000005: public Class1() { IL_0000: /* 02 | */ ldarg.0 IL_0001: /* 28 | (0A)000011 */ call instance void [mscorlib/*23000001*/]System.Object/*01000001*/::.ctor() /* 0A000011 */ IL_0006: /* 00 | */ nop IL_0007: /* 00 | */ nop //000006: // array initializer, want to read '99', '100' etc. //000007: var a = new double[,] { { 1, 2, 3 }, { 99, 100, 101 } }; IL_0008: /* 18 | */ ldc.i4.2 IL_0009: /* 19 | */ ldc.i4.3 IL_000a: /* 73 | (0A)000012 */ newobj instance void float64[0...,0...]/*1B000001*/::.ctor(int32, int32) /* 0A000012 */ IL_000f: /* 25 | */ dup IL_0010: /* D0 | (04)000001 */ ldtoken field valuetype '<PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}'/*02000003*//'__StaticArrayInitTypeSize=48'/*02000004*/ '<PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}'/*02000003*/::'$$method0x6000001-1' /* 04000001 */ IL_0015: /* 28 | (0A)000014 */ call void [mscorlib/*23000001*/]System.Runtime.CompilerServices.RuntimeHelpers/*01000015*/::InitializeArray(class [mscorlib/*23000001*/]System.Array/*01000016*/, valuetype [mscorlib/*23000001*/]System.RuntimeFieldHandle/*01000017*/) /* 0A000014 */ IL_001a: /* 0A | */ stloc.0 //000008: // ... //000009: } IL_001b: /* 00 | */ nop IL_001c: /* 2A | */ ret } // end of method Class1::.ctor 

The compiler created struct <PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4} with the $$method0x6000001-1 field for the initialization value and uses RuntimeHelpers.InitializeArray to initialize the new array at runtime. The original values ​​defined in C # are apparently stored in the field and copied using the field descriptor? But how are the values?

Should there be some better / easier way to read these constants from the assembly?

+6
source share
1 answer

no answer

What you are trying to do on the impossible (note that one case in your example is probably feasible, but probably won't cover your full needs)

<PrivateImplementationDetails> is created by the C # compiler only in some cases (for example, numeric arrays of a certain size). For all other cases, direct initialization is performed in the constructor. For some examples, see http://goo.gl/iC6MRv .

Please note that the IL code that you see is not "written on the stone" ... There are no rules that dictate to the C # compiler how it should create array initializers. For example, Roslyn (the link I gave is generated by Roslyn) uses PrivateImplementationDetails instead of <PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4} . And who knows what code is generated by the Mono compiler.

In the most general case, it is impossible to know the values ​​of the initialized array without executing the constructor (so there is an instance of the class) and look at the resulting object. But this obviously has other problems (class initialization may have side effects or may require parameters)

+7
source

Source: https://habr.com/ru/post/987792/


All Articles