2015-08-24 43 views
5

Ben IL koduna bu basit sınıfını dönüştürmek çalışıyorum: Basit sınıfı IL'ye dönüştürmek bazı geçersiz IL kodları nedeniyle başarısız oldu mu?

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

Aslında ben dinamik olarak sınıf oluşturmak için Emit kullanmayı denemeden önce IL talimatlarını bilmek ILDasm kullandı. gösterir sonucudur: Bu itibaren

.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 

, böyle Emit kullanarak çalıştı: kullanmaktan Şimdi

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

deneyin: IL kodu yanlış olur demektir

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

bir noktada. Ama aslında ILDasm tarafından üretilen ile karşılaştırıldığında, ben hiçbir fark görmüyorum. Burada sorun nedir?

cevap

6

IL_0006, IL_0007 ve IL_0013 satırlarında başvurulan yerel değişkeni bildirmeyi kaçırdınız. Aşağıdaki satırı ekleyin ve işe yarayacak. Kod, hata ayıklama modunda derlendiği için, bu yerel derleyici tarafından tanıtıldı, büyük olasılıkla bu yerel, büyük olasılıkla, tanıtıcı tarafından tanıtıldı.

+0

Teşekkür ederim, eğer daha iyi anlamış olsaydım tamam olurdu. – Hopeless