2015-08-24 22 views
5

Ich versuche, diese einfache Klasse zu IL-Code zu konvertieren:Die Konvertierung der einfachen Klasse in IL ist aufgrund eines ungültigen IL-Codes fehlgeschlagen?

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

In der Tat habe ich ILDasm die IL Anweisungen zu kennen, bevor Emit zu verwenden versuchen, dynamisch die Klasse zu erstellen. Das Ergebnis zeigt es ist:

.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 

Von diesem habe ich versucht, Emit wie folgt aus:

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); 

Jetzt versuchen Sie es mit:

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

Das bedeutet, dass die IL-Code falsch wäre, irgendwann. Aber verglichen mit dem, was tatsächlich von ILDasm generiert wird, sehe ich keinen Unterschied. Was ist hier falsch?

Antwort

6

Sie haben versäumt, die lokale Variable zu deklarieren, auf die in der Zeile IL_0006, IL_0007 und IL_0013 verwiesen wird. Fügen Sie die folgende Zeile hinzu und es wird funktionieren.

Am wahrscheinlichsten wurde diese lokale vom Compiler eingeführt, weil der Code im Debug-Modus kompiliert wurde.

+0

danke, es wäre in Ordnung gewesen, wenn ich IL besser verstanden hätte. – Hopeless