2015-08-24 7 views
5

मैं आईएल कोड को यह साधारण क्लास कन्वर्ट करने के लिए कोशिश कर रहा हूँ:कुछ अवैध आईएल कोड के कारण सरल वर्ग से आईएल में कनवर्ट करना विफल रहा?

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

वास्तव में मैं ILDasm इस्तेमाल किया Emit उपयोग करने के लिए गतिशील रूप से वर्ग बनाने के लिए प्रयास करने से पहले आईएल निर्देश को पता है। परिणाम यह पता चलता है है:

.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." 

इसका मतलब है कि आईएल कोड गलत होगा किन्हीं बिंदुओं पर। लेकिन वास्तव में ILDasm द्वारा जेनरेट की गई चीज़ों की तुलना में, मुझे कोई अंतर दिखाई नहीं देता है। यहाँ क्या गलत है?

उत्तर

6

आप स्थानीय आईएल_0006, आईएल_0007 और आईएल_0013 में संदर्भित स्थानीय चर घोषित करने के लिए चूक गए। निम्नलिखित पंक्ति जोड़ें और यह काम करेगा।

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

अधिकतर इस स्थानीय को कंपाइलर द्वारा पेश किया गया था, क्योंकि कोड डीबग मोड में संकलित किया गया था।

+0

धन्यवाद, अगर मैं बेहतर आईएल समझ गया तो यह ठीक रहेगा। – Hopeless

संबंधित मुद्दे