当尝试创建新类型时InvalidProgramException
本文关键字:类型 InvalidProgramException 创建 新类型 | 更新日期: 2023-09-27 18:18:37
我有以下代码:
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 -公共语言运行库检测到一个无效的程序。
我的代码出了什么问题,为什么会抛出这个异常?
问题是lambda表达式包含一个字符串,该字符串在编译时不是以方法体结束,而是以类型的元数据结束。lambda中的ldstr
指令通过元数据令牌引用字符串。当您获得IL字节并将其复制到新方法时,新方法中的ldstr
将具有无效的元数据令牌。
如果要我猜的话,我会说是因为这一行:
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();