我正在尝试创建一个基本上包含静态类上的某些方法的动态类型。我创建了一个名为Wrap的静态方法,它有一个应该是接口的泛型参数,以及一个普通参数,它是具有静态方法的类的类型。
e.g。
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);
}
}
答案 0 :(得分:3)
主要是,我认为这与您对退货类型的处理有关:
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_0
和Ldloc_0
是非法的所以更简单(和工作)的实现只是:
ilgen.EmitCall(OpCodes.Call, callMeth, null);
ilgen.Emit(OpCodes.Ret);