1

我有例外:操作可能會破壞運行時,我不知道爲什麼:(請幫我如何從單調用實例方法與EMIT

我加了本地,但仍然沒有工作......

方法要動態創建(REF000001):

public static int REF000001(int REF000002, object REF000003, DateTime REF000004) 
    { 
     return (int)typeof(REF000005).GetMethod("REF000006", new Type[] { typeof(int), typeof(object), typeof(DateTime) }).Invoke(REF000005.REF000008(), new object[] { REF000002, REF000003, REF000004 }); 
    } 

這是類,我想從單調用方法

​​3210 。從ILDASM

返回:

.method public hidebysig static int32 REF000001(int32 REF000002, 
              object REF000003, 
              valuetype [mscorlib]System.DateTime REF000004) cil  managed 
{ 
// Code size  118 (0x76) 
.maxstack 5 
.locals init ([0] int32 CS$1$0000, 
     [1] class [mscorlib]System.Type[] CS$0$0001, 
     [2] object[] CS$0$0002) 
IL_0000: nop 
IL_0001: ldtoken ConsoleApplication3.REF000005 
IL_0006: call  class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 
IL_000b: ldstr  "REF000006" 
IL_0010: ldc.i4.3 
IL_0011: newarr  [mscorlib]System.Type 
IL_0016: stloc.1 
IL_0017: ldloc.1 
IL_0018: ldc.i4.0 
IL_0019: ldtoken [mscorlib]System.Int32 
IL_001e: call  class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 
IL_0023: stelem.ref 
IL_0024: ldloc.1 
IL_0025: ldc.i4.1 
IL_0026: ldtoken [mscorlib]System.Object 
IL_002b: call  class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 
IL_0030: stelem.ref 
IL_0031: ldloc.1 
IL_0032: ldc.i4.2 
IL_0033: ldtoken [mscorlib]System.DateTime 
IL_0038: call  class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 
IL_003d: stelem.ref 
IL_003e: ldloc.1 
IL_003f: call  instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string, 
                              class [mscorlib]System.Type[]) 
IL_0044: call  class ConsoleApplication3.REF000005 ConsoleApplication3.REF000005::REF000008() 
IL_0049: ldc.i4.3 
IL_004a: newarr  [mscorlib]System.Object 
IL_004f: stloc.2 
IL_0050: ldloc.2 
IL_0051: ldc.i4.0 
IL_0052: ldarg.0 
IL_0053: box  [mscorlib]System.Int32 
IL_0058: stelem.ref 
IL_0059: ldloc.2 
IL_005a: ldc.i4.1 
IL_005b: ldarg.1 
IL_005c: stelem.ref 
IL_005d: ldloc.2 
IL_005e: ldc.i4.2 
IL_005f: ldarg.2 
IL_0060: box  [mscorlib]System.DateTime 
IL_0065: stelem.ref 
IL_0066: ldloc.2 
IL_0067: callvirt instance object [mscorlib]System.Reflection.MethodBase::Invoke(object, 
                        object[]) 
IL_006c: unbox.any [mscorlib]System.Int32 
IL_0071: stloc.0 
IL_0072: br.s  IL_0074 
IL_0074: ldloc.0 
IL_0075: ret 
} // end of method Program::REF000001 

我與IL發電機拋出異常操作的代碼可能會破壞運行時

static DynamicMethod Method1A() 
    { 
     DynamicMethod method1 = new DynamicMethod("Dodaj", typeof(void), new Type[] { typeof(int), typeof(object), typeof(DateTime) }); 
     ILGenerator il = method1.GetILGenerator(); 

     Label target = il.DefineLabel(); 

     var tps = il.DeclareLocal(typeof(Type[])); 
     var obs = il.DeclareLocal(typeof(object[])); 

     il.Emit(OpCodes.Ldtoken, typeof(REF000005)); 
     il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[1] { typeof(RuntimeTypeHandle) })); 
     il.Emit(OpCodes.Ldstr, "REF000006"); 

     il.Emit(OpCodes.Ldc_I4_3); 
     il.Emit(OpCodes.Newarr, typeof(Type)); 
     il.Emit(OpCodes.Stloc, tps); 
     il.Emit(OpCodes.Ldloc, tps); 
     il.Emit(OpCodes.Ldc_I4_0); 
     il.Emit(OpCodes.Ldtoken, typeof(Int32)); 
     il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[1] { typeof(RuntimeTypeHandle) })); 
     il.Emit(OpCodes.Stelem_Ref); 
     il.Emit(OpCodes.Ldloc, tps); 
     il.Emit(OpCodes.Ldc_I4_1); 
     il.Emit(OpCodes.Ldtoken, typeof(Object)); 
     il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[1] { typeof(RuntimeTypeHandle) })); 
     il.Emit(OpCodes.Stelem_Ref); 
     il.Emit(OpCodes.Ldloc, tps); 
     il.Emit(OpCodes.Ldc_I4_2); 
     il.Emit(OpCodes.Ldtoken, typeof(DateTime)); 
     il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[1] { typeof(RuntimeTypeHandle) })); 
     il.Emit(OpCodes.Stelem_Ref); 
     il.Emit(OpCodes.Ldloc, tps); 

     il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetMethod", new Type[2] { typeof(string), typeof(Type[]) })); 
     il.Emit(OpCodes.Call, typeof(REF000005).GetMethod("REF000008")); 

     il.Emit(OpCodes.Ldc_I4_3); 
     il.Emit(OpCodes.Newarr, typeof(object)); 
     il.Emit(OpCodes.Stloc, obs); 
     il.Emit(OpCodes.Ldloc, obs); 
     il.Emit(OpCodes.Ldc_I4_0); 
     il.Emit(OpCodes.Ldarg, 0); 
     il.Emit(OpCodes.Box, typeof(Int32)); 
     il.Emit(OpCodes.Stelem_Ref); 
     il.Emit(OpCodes.Ldloc, obs); 
     il.Emit(OpCodes.Ldc_I4_1); 
     il.Emit(OpCodes.Ldarg, 1); 
     //il.Emit(OpCodes.Box, typeof(object)); 
     il.Emit(OpCodes.Stelem_Ref); 
     il.Emit(OpCodes.Ldloc, obs); 
     il.Emit(OpCodes.Ldc_I4_2); 
     il.Emit(OpCodes.Ldarg, 2); 
     il.Emit(OpCodes.Box, typeof(DateTime)); 
     il.Emit(OpCodes.Stelem_Ref); 
     il.Emit(OpCodes.Ldloc, obs); 
     il.Emit(OpCodes.Box, typeof(object[])); 
     il.Emit(OpCodes.Callvirt, typeof(MethodBase).GetMethod("Invoke", new Type[2] { typeof(object), typeof(object[]) })); 
     il.Emit(OpCodes.Unbox_Any, typeof(Int32)); 
     il.Emit(OpCodes.Ret); 
     return method1; 
    } 
+0

它看起來像你忘了[聲明你的本地變量](http://msdn.microsoft.com/en-us/library/y1xffef4.aspx)。 – svick

+0

我添加本地,並更改我的代碼,但仍然無法正常工作。請你幫我一下。 – user2807597

回答

3

有你複製的方法和正在創建的一個之間的差異:前者返回int,後者void。這正是您的代碼無法工作的原因:當您從void方法返回時,堆棧必須是空的;當您從非void方法返回時,堆棧必須包含要返回的值(並且不包含其他值)。

找出這類問題的最好方法是在動態程序集的類型中創建方法,將該程序集保存到磁盤,然後在其上運行PEVerify。

要解決此問題,您可以將您創建的方法的返回類型更改爲int。另一種選擇是在ret之前將方法void,但pop保留在堆棧上。


話雖這麼說,我真的不明白你試圖在這裏完成的。你的C#方法已經完成你所需要的,沒有必要爲此使用Reflection.Emit。如果你想使用Reflection.Emit來避免使用反射的性能損失,你不能只使用IL中的反射。

+0

感謝,peverify是偉大的:) – user2807597

+0

@ user2807597如果你認爲我的asnwer實際上回答了你的問題,你應該[接受它](http://meta.stackexchange.com/a/5235/130186)。 – svick

相關問題