C# 如何从.NET程序集中读取数组初始值设定项值

C# 如何从.NET程序集中读取数组初始值设定项值,c#,.net,reflection,.net-assembly,il,C#,.net,Reflection,.net Assembly,Il,如何从包含此代码的程序集中读取值,例如:“99” 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 } }; // ... } } 到目前为

如何从包含此代码的程序集中读取值,例如:“99”

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 } };
        // ...
    }

}
到目前为止我做了什么 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
.method/*06000001*/public hidebysing specialname rtspecialname
实例void.ctor()cil托管
//信号:20 00 01
{
//方法从RVA 0x2080开始
//代码大小29(0x1d)
.maxstack 3
.locals/*11000001*/init([0]float64[0…,0…]a)
.语言“{3F5162F8-07C6-11D3-9053-00C04FA302A1}”,{994B45C4-E6E9-11D2-903F-00C04FA302A1},{5A869D0B-6611-11D3-BD2A-0000F849BD}”
//源文件“c:\Users\heini19\Documents\Visual Studio 2013\Projects\WcfService1\ClassLibrary1\Class1.cs”
//000005:公共类别1(){
IL_0000:/*02 |*/ldarg.0
IL_0001:/*28 |(0A)000011*/调用实例void[mscorlib/*23000001*/]System.Object/*01000001*/:.ctor()/*0A000011*/
IL_0006:/*00 |*/nop
IL_0007:/*00 |*/nop
//000006://数组初始值设定项,要读取“99”、“100”等。
//000007:var a=新的双[,]{1,2,3},{99100101};
IL_0008:/*18 |*/ldc.i4.2
IL_0009:/*19 |*/ldc.i4.3
IL_000a:/*73 |(0A)000012*/newobj实例void float64[0…,0…]/*1B00001*/:.ctor(int32,
int32)/*0A000012*/
IL_000f:/*25 |*/dup
IL_0010:/*D0 |(04)000001*/ldtoken字段值类型“{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}”/*0200003*/''\uu staticaryInittypesize=48'/*0200004*/{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}”/*02000003*:$$method0x600001-1/*00001*/
IL_0015:/*28 |(0A)000014*/调用void[mscorlib/*23000001*/]System.Runtime.CompilerServices.RuntimeHelpers/*01000015*/::InitializeArray(类[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
}//方法Class1的结尾::.ctor
编译器创建了结构
{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}
,其中字段
$$method0x6000001-1
作为初始化值,并使用
RuntimeHelpers.InitializeArray
在运行时初始化新数组。C#中定义的原始值似乎存储在字段中,并通过使用字段句柄进行复制?但这些价值观是如何体现的呢


必须有更好/更简单的方法从程序集中读取这些常量?

无响应

您试图做的事情几乎是不可能的(请注意,您的示例中的单个案例可能是可行的,但可能无法满足您的全部需求)

仅在某些情况下由C#编译器创建(似乎是特定大小的数字数组)。对于所有其他情况,构造函数中的直接初始化都已完成。有关一些示例,请参见

请注意,您看到的IL代码不是“写在石头上的”。。。没有规则规定C#编译器应该如何创建数组初始值设定项。例如,Roslyn(我给出的链接是由Roslyn生成的)使用了
PrivateImplementationDetails
而不是
{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}
。谁知道Mono编译器会生成什么代码呢


在最常见的情况下,如果不执行构造函数(实例化类)并查看获得的对象,就不可能知道初始化数组的值。但这显然还有其他问题(类的初始化可能有副作用,或者可能需要参数)

这是XY问题的一个实例吗?你一开始为什么要这么做?你到底想达到什么目的?这是什么?它将用于程序集版本控制所需的程序集哈希算法。必须以某种方式检测对这些常量(代码中)的更改。@HaymoKutschbach您可以使用一些基本类型数组。。。但是,对于对象数组(可能是由方法返回的)您将怎么做?(
new[]{GetElement1(),GetElement2(),GetElement3()}
)@HaymoKutschbach The。。。你的问题似乎不是XY问题。。。只是一个很奇怪的问题problem@HaymoKutschbach请注意,“隐藏特殊”类仅在一种情况下调用。。。大小>=3的数值类型数组。我们无法从程序集轻松了解初始化结果,这听起来很合理。另一方面,像reflector/Cecil这样的工具似乎可以。但也许为了散列的目的,我们可以简单地包括存储这些常量的程序集的“区域”。你认为我们可以概括所有编译器处理这个问题的方式吗?它们都将这些常量存储在helper类字段中,对吗?在散列中包含所有字段可能就足够了?@HaymoKutschbach IlSpy只需检查数组初始值设定项的某些模式。他们可能用C#、Mono C#、VB.NET或者F#来测试它。代码是。不能保证C#的未来版本会产生相同的模式,或者其他编译器会产生相同的模式,或者手工编写的IL代码会使用相同的模式。链接非常有用!我希望我能不止一次地向上投票:)你能告诉我一些关于初始值在自动生成的类字段中存储方式的资源吗?也散列这些内部类就足够了吗?(不考虑编译器兼容性)