【发布时间】:2015-09-03 23:16:38
【问题描述】:
我正在尝试使用 Reflection.Emit 生成代码,该代码看起来与 C# 编译器为此生成的代码相同或相似:
public interface Function<in T, out Res>
{
Res Apply(T p);
}
public class MyMain<A>
{
class Closure : Function<A, A>
{
public A Apply(A p)
{
throw new NotImplementedException();
}
}
}
如果我使用一些真实类型,我的代码可以正常工作,但是当我用泛型替换它时,我得到 BadImageFormatException。
private static void CreateGenericClosures()
{
AssemblyName assemblyName = new AssemblyName("genericClosure");
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
TypeBuilder main = moduleBuilder.DefineType("Main", TypeAttributes.Class | TypeAttributes.Public);
Type t = typeof (Foo);
// Defining generic param for Main class
GenericTypeParameterBuilder[] generics = main.DefineGenericParameters("A");
// t = generics[0]; // [1] Uncomment to enable for nested class
var iFunctionType = typeof (Function<,>).MakeGenericType(t, t);
TypeBuilder closure = main.DefineNestedType("Closure", TypeAttributes.Class | TypeAttributes.NestedPrivate, typeof (object));
closure.AddInterfaceImplementation(iFunctionType);
MethodBuilder applyMethod = closure.DefineMethod("Apply",
MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.Public,
CallingConventions.Standard);
applyMethod.SetParameters(t);
applyMethod.SetReturnType(t);
ILGenerator body = applyMethod.GetILGenerator();
body.Emit(OpCodes.Ldnull);
body.Emit(OpCodes.Ret);
closure.DefineDefaultConstructor(MethodAttributes.Public);
closure.CreateType();
main.CreateType();
assemblyBuilder.Save(assemblyName.Name + ".dll", PortableExecutableKinds.Required32Bit, ImageFileMachine.I386);
}
取消注释 [1] 以查看异常。 有什么想法可能是错的吗?
【问题讨论】:
-
PEVerify 对您的程序集有何评价?
-
我无法在该程序集上运行 PEVerify,因为它在保存程序集之前会引发异常。我检查了单 C# 编译器如何处理这种情况,并在嵌套类型上调用 DefineGenericParameters。因此,如果我这样做,它工作正常,但不清楚为什么需要这样做,我是否需要匹配泛型类型名称。
标签: c# generics nested reflection.emit