尝试创建新类型时出现InvalidProgramException

时间:2015-10-20 19:06:30

标签: c# .net reflection types reflection.emit

我有以下代码:

AssemblyBuilder newAssembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("CustomAssembly"), AssemblyBuilderAccess.Run);
ModuleBuilder newModule = newAssembly.DefineDynamicModule("CustomModule");
TypeBuilder newType = newModule.DefineType("CustomType", TypeAttributes.Public);
MethodBuilder newMethod = newType.DefineMethod("GetMessage", MethodAttributes.Public, typeof(string), Type.EmptyTypes);
byte[] methodBody = ((Func<string>)(() => "Hello, world!")).GetMethodInfo().GetMethodBody().GetILAsByteArray();
newMethod.CreateMethodBody(methodBody, methodBody.Length);
Type customType = newType.CreateType();
dynamic myObject = Activator.CreateInstance(customType);
string message = myObject.GetMessage();

但是,尝试调用myObject.GetMessage()时,最后一行会抛出异常:

  

InvalidProgramException - 公共语言运行时检测到无效程序。

我的代码有什么问题,为什么抛出这个异常?

2 个答案:

答案 0 :(得分:2)

问题是lambda表达式包含一个字符串,当编译时,字符串不是以方法体结尾,而是在类型的元数据中结束。 lambda中的ldstr指令通过元数据标记引用字符串。当您获得IL字节并复制到新方法时,新方法中的ldstr将具有无效的元数据标记。

答案 1 :(得分:1)

如果我不得不冒险猜测,我会说这是因为这句话:

byte[] methodBody = ((Func<string>)(() => "Hello, world!")).GetMethodInfo().GetMethodBody().GetILAsByteArray();

我不确定签名(Func<string>)( () => "Hello, world!" )究竟是什么,但它可能不是正确的(一个接受你定义类型的隐含参数)。

我建议使用方法构建器的GetILGenerator方法来执行此操作:

AssemblyBuilder newAssembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("CustomAssembly"), AssemblyBuilderAccess.Run);
ModuleBuilder newModule = newAssembly.DefineDynamicModule("CustomModule");
TypeBuilder newType = newModule.DefineType("CustomType", TypeAttributes.Public);
MethodBuilder newMethod = newType.DefineMethod("GetMessage", MethodAttributes.Public, typeof(string), Type.EmptyTypes);

var il = newMethod.GetILGenerator();
// return "Hello, world!";
il.Emit( OpCodes.Ldstr, "Hello, world!" );
il.Emit( OpCodes.Ret );

Type customType = newType.CreateType();
dynamic myObject = Activator.CreateInstance(customType);
string message = myObject.GetMessage();
相关问题