1

У меня есть исключение:. Операция может дестабилизировать выполнения, и я не знаю почему :(Пожалуйста, помогите мнеКак вызвать метод экземпляра из одноэлементных с Emit

Я Добавлен Local, но до сих пор не работает ...

.

метод хочет создать динамически (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 }); 
    } 

Это класс, который я хочу, чтобы вызвать метод из одноэлементного

public class REF000005 
{ 
    private static REF000005 REF000007; 

    private REF000005() 
    { 

    } 

    public static REF000005 REF000008() 
    { 
     if (REF000007 == null) 
      REF000007 = new REF000005(); 

     return REF000007; 
    } 

    public int REF000006(int REF000009, object REF000010, DateTime REF000011) 
    { 
     return 5; 
    } 
} 
.

Возвращение из 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

Я добавляю Local и меняю свой код, но все равно не работаю. Мог бы помочь мне, пожалуйста. – user2807597

ответ

3

Там разница между методом вы копируете и тот, который вы создаете : прежний возвращает int, последний void. Именно поэтому ваш код не работает: когда вы возвращаетесь из метода void, стек должен быть пустым; когда вы возвращаетесь из метода не void, стек должен содержать возвращаемое значение (и ничего больше).

Лучший способ узнать об этих проблемах - создать свой метод в типе динамической сборки, сохранить эту сборку на диск и затем запустить PEVerify.

Чтобы исправить это, вы можете изменить тип возвращаемого метода, который вы создаете, на int. Другим вариантом было бы сохранить метод void, но pop элемент в стеке прямо перед вами ret.


Это, как говорится, я действительно не понимаю, что вы пытаетесь выполнить здесь. Ваш метод C# уже делает именно то, что вам нужно, нет необходимости использовать Reflection.Emit для этого. И если вы хотите использовать Reflection.Emit, чтобы избежать снижения производительности при использовании отражения, вы не можете просто использовать отражение от своего IL.

+0

спасибо, peverify is great :) – user2807597

+0

@ user2807597 Если вы думаете, что мой asnwer ответил на ваш вопрос, вы должны [принять его] (http://meta.stackexchange.com/a/5235/130186). – svick