我有例外:操作可能会破坏运行时的稳定性,我不知道为什么:(。请帮助我。
我添加了本地,但仍然无法正常工作...
方法想要动态创建 (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;
}
您正在复制的方法和您正在创建的方法之间存在差异:前者返回int
,后者返回void
。这正是您的代码不起作用的原因:当您从 void
方法返回时,堆栈必须是空的;当您从非void
方法返回时,堆栈必须包含要返回的值(而不是其他任何内容)。
了解此类问题的最佳方法是在动态程序集的类型中创建方法,将该程序集保存到磁盘,然后对其运行 PEVerify。
若要解决此问题,可以将要创建的方法的返回类型更改为 int
。另一种选择是将方法保持void
,但在ret
之前将元素pop
堆栈上。
话虽如此,我真的不明白你在这里想要完成什么。您的 C# 方法已经完全满足了您的需求,无需为此使用 Reflection.Emit。如果要使用 Reflection.Emit 来避免使用反射的性能损失,则不能只使用 IL 中的反射。