gpt4 book ai didi

c# - InvalidProgramException 试图通过 Reflection.Emit 调用静态方法

转载 作者:行者123 更新时间:2023-11-30 22:25:36 25 4
gpt4 key购买 nike

我正在尝试创建一个动态类型,它基本上将一些方法包装在静态类上。我创建了一个名为 Wrap 的静态方法,它有一个通用参数,它应该是一个接口(interface),还有一个普通参数,它是具有静态方法的类的类型。

例如

IInterfaceTest obj = StaticInterface.Wrap<IInterfaceTest>(typeof(StaticClassNameHere));
obj.TestInterfaceMethod();

但是我生成的代码显然在某处被破坏了,因为当我调用该方法时出现 InvalidProgramException。

我的代码基于我创建的测试类的 ILDasm 输出,据我所知,我正在输出相同的代码。但是它不起作用...

public static class StaticInterface
{
private static AssemblyBuilder _asm = null;
private static ModuleBuilder _mod = null;
private static Type _thisType = typeof(StaticInterface);
private static int _count = 0;
public static T Wrap<T>(Type type)
{
ILGenerator ilgen;

if (_asm == null)
{
_asm = AppDomain.CurrentDomain.DefineDynamicAssembly(new System.Reflection.AssemblyName(_thisType.Name), AssemblyBuilderAccess.Run);
_mod = _asm.DefineDynamicModule(_thisType.Name);
}

string newTypeName = _thisType.Name + "._" + _count++;

TypeBuilder typBuilder = _mod.DefineType(newTypeName, System.Reflection.TypeAttributes.Class | System.Reflection.TypeAttributes.Public);
typBuilder.AddInterfaceImplementation(typeof(T));

ConstructorBuilder conBuilder = typBuilder.DefineDefaultConstructor(System.Reflection.MethodAttributes.Public);

foreach (MethodInfo method in typeof(T).GetMethods())
{
ParameterInfo[] parameters = method.GetParameters();
Type[] paramTypes = new Type[parameters.Length];

for (int j = 0; j < parameters.Length; j++)
{
paramTypes[j] = parameters[j].ParameterType;
}

MethodBuilder mth = typBuilder.DefineMethod(method.Name,
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Final,
method.ReturnType,
paramTypes);

ilgen = mth.GetILGenerator();
ilgen.Emit(OpCodes.Nop);

for (short j = 0; j < parameters.Length; j++)
{
ilgen.Emit(OpCodes.Ldarg, j + 1);
}

MethodInfo callMeth = type.GetMethod(method.Name, BindingFlags.Public | BindingFlags.Static, null, paramTypes, null);

ilgen.EmitCall(OpCodes.Call, callMeth, null);

if (method.ReturnType != null && method.ReturnType != typeof(void))
{
ilgen.Emit(OpCodes.Stloc_0);
Label end = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Br_S, end);

ilgen.MarkLabel(end);
ilgen.Emit(OpCodes.Ldloc_0);
}

ilgen.Emit(OpCodes.Ret);
}

typBuilder.CreateType();

return (T)_asm.CreateInstance(newTypeName, false, BindingFlags.Public | BindingFlags.Instance, null, null, null, null);
}
}

最佳答案

我认为这主要与您对返回类型的处理有关:

ilgen.EmitCall(OpCodes.Call, callMeth, null);
if (method.ReturnType != null && method.ReturnType != typeof(void))
{
ilgen.Emit(OpCodes.Stloc_0);
Label end = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Br_S, end);

ilgen.MarkLabel(end);
ilgen.Emit(OpCodes.Ldloc_0);
}
ilgen.Emit(OpCodes.Ret);
  • 你还没有定义任何局部变量,所以 STLoc_0Ldloc_0 是非法的
  • 分支只是......分支到下一行(所以什么都不做),所以这基本上是“存储到 X,从 X 加载”,如果我们不关心侧面的话,这是一个空操作 -分配 X 的效果
  • 这完全没有必要无论如何 - 只需将返回值留在堆栈上,因为它需要匹配(意思是:如果该方法没有返回值,那没关系;如果它 < em>确实返回一个值,那么该值已经是堆栈上的值——即正是我们想要的)

所以更简单(和有效)的实现是:

ilgen.EmitCall(OpCodes.Call, callMeth, null);
ilgen.Emit(OpCodes.Ret);

关于c# - InvalidProgramException 试图通过 Reflection.Emit 调用静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12195611/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com