c# - 由于一些无效的 IL 代码,将简单类转换为 IL 失败?

标签 c# dynamic reflection reflection.emit il

我正在尝试将这个简单的类转换为 IL 代码:

public class IL {
  Dictionary<string, int> props = new Dictionary<string, int>() { {"1",1} };
}

事实上,在尝试使用 Emit 动态创建类之前,我使用 ILDasm 来了解 IL 指令。它显示的结果是:

.class public auto ansi beforefieldinit IL
   extends [mscorlib]System.Object
{
 .field private class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32> props
 .method public hidebysig specialname rtspecialname 
      instance void  .ctor() cil managed
 {
 // 
 .maxstack  4
 .locals init (class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32> V_0)
 IL_0000:  ldarg.0
 IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::.ctor()
 IL_0006:  stloc.0
 IL_0007:  ldloc.0
 IL_0008:  ldstr      "1"
 IL_000d:  ldc.i4.1
 IL_000e:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
                                                                                                              !1)
 IL_0013:  ldloc.0
 IL_0014:  stfld      class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32> IL::props
 IL_0019:  ldarg.0
 IL_001a:  call       instance void [mscorlib]System.Object::.ctor()
 IL_001f:  ret
 } // end of method IL::.ctor

} // end of class IL

由此,我尝试像这样使用 Emit:

var aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new System.Reflection.AssemblyName("test"), AssemblyBuilderAccess.Run);
var mBuilder = aBuilder.DefineDynamicModule("module");
var tBuilder = mBuilder.DefineType("IL");        
var field = tBuilder.DefineField("props", typeof(Dictionary<string, int>), System.Reflection.FieldAttributes.Private);
var con = tBuilder.DefineConstructor(System.Reflection.MethodAttributes.Public | 
                       System.Reflection.MethodAttributes.HideBySig | 
                       System.Reflection.MethodAttributes.SpecialName | 
                       System.Reflection.MethodAttributes.RTSpecialName, 
                       System.Reflection.CallingConventions.HasThis, Type.EmptyTypes);

var conIL = con.GetILGenerator();            
conIL.Emit(OpCodes.Ldarg_0);            
conIL.Emit(OpCodes.Newobj, typeof(Dictionary<string,int>).GetConstructor(Type.EmptyTypes));                        
conIL.Emit(OpCodes.Stloc_0);                
conIL.Emit(OpCodes.Ldloc_0);
conIL.Emit(OpCodes.Ldstr, "1");
conIL.Emit(OpCodes.Ldc_I4_1);
conIL.Emit(OpCodes.Callvirt, typeof(Dictionary<string, int>).GetMethod("Add"));
conIL.Emit(OpCodes.Ldloc_0);
conIL.Emit(OpCodes.Stfld, field);

conIL.Emit(OpCodes.Ldarg_0);
conIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
conIL.Emit(OpCodes.Ret);

现在尝试使用它:

var t =  tBuilder.CreateType();
var instance = Activator.CreateInstance(t);//exception has been thrown here 
               //saying "Common Language Runtime detected an invalid program."

这意味着 IL 代码在某些时候会出错。但是将它与 ILDasm 实际生成的内容进行比较,我看不出有什么不同。这里有什么问题?

最佳答案

您没有声明在 IL_0006、IL_0007 和 IL_0013 行中引用的局部变量。添加以下行,它将起作用。

conIL.DeclareLocal(typeof (Dictionary<string, int>), false);

这个本地很可能是由编译器引入的,因为代码是在 Debug模式下编译的。

关于c# - 由于一些无效的 IL 代码,将简单类转换为 IL 失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32172789/

相关文章:

c# - 为什么要使用 glTranslate?

c# - 如何将文件复制到网络路径

javascript - 在 AspNetCore 中使用 Rotativa 将 Html 转换为 Pdf

javascript - 为什么我的增量器返回一个对象? id_[对象 HTMLInputElement]

dynamic - Common Lisp 作用域(动态 vs 词法)

c# - 将接口(interface)的 ProperyInfo 与类的 PropertyInfo 匹配

c# - 在 .Net 中恢复本地名称

c# - 如何在不知道所有参数的情况下动态调用对象的构造函数?

动态表单生成器的数据库模式

java - 我可以使用正则表达式来查找java中类的方法吗?