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

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

}

到目前为止我做了什么

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

编译器创建了结构 <PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}与现场 $$method0x6000001-1对于初始化值并使用 RuntimeHelpers.InitializeArray为了在运行时初始化新数组。 C# 中定义的原始值似乎存储在字段中并通过使用字段句柄进行复制?但是这些值是如何设置的呢?

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

最佳答案

无 react

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

<PrivateImplementationDetails>仅在某些情况下由 C# 编译器创建(似乎是超过一定大小的数字数组)。对于所有其他情况,构造函数中的直接初始化已完成。参见 http://goo.gl/iC6MRv举一些例子。

请注意,您看到的 IL 代码并非“一成不变”……没有任何规则指示 C# 编译器应如何创建数组初始值设定项。例如 Roslyn(我给出的链接是由 Roslyn 生成的)使用 PrivateImplementationDetails而不是 <PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4} .谁知道 Mono 编译器生成了什么代码。

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

关于c# - 如何从 .NET 程序集中读取数组初始值设定项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30414300/

相关文章:

c# - 是否有可能捕获您无法处理的异常(在 C# 中)?

c# - Task.WaitAll 卡住应用程序 C#

c# - 关于在 Thread 中传递的局部变量

.net - SQL Server 和 .net 支持使用参数值调用存储过程而不提供参数名称吗?

java - java中使用泛型类型代替反射来创建实例

c# - 使用 C# 从 SQL Server 数据库显示 PDF

c# - Windows 服务启动时抛出 "System.ComponentModel.Win32Exception: Access is denied"

c# - 比较两个复杂对象的最佳方法

java - Java中如何获取一个类的所有子类?

c# - 从项目中获取引用位置