2015-10-20 3 views
1

У меня есть следующий код:InvalidProgramException при попытке создать новый тип

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(); 

Однако исключение брошено на последней строке, когда tryingto вызов myObject.GetMessage():

InvalidProgramException - Common Language Runtime обнаружена неверная программа.

Что не так с моим кодом и почему это исключение выбрасывается?

ответ

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(); 
1

Проблема заключается в том, что лямбда-выражение включает в себя строку, которая при компиляции заканчивается не с телом метода, но в метаданных типа по , Инструкция ldstr в лямбда относится к строке через токен метаданных. Когда вы получите байты IL и скопируете затем новый метод, ldstr в новом методе будет иметь недопустимый токен метаданных.

Смежные вопросы