1

I have the following code:

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

However, an exception is thrown on the last line when tryingto call myObject.GetMessage():

InvalidProgramException - Common Language Runtime detected an invalid program.

What is wrong with my code and why is this exception being thrown?

2 Answers 2

2

The problem is that the lambda expression includes a string, which when compiled ends not with the method body but in the type's metadata. The ldstr instruction in the lambda refers to the string via a metadata token. When you get the IL bytes and copy then to the new method the ldstr in the new method will have an invalid metadata token.

Sign up to request clarification or add additional context in comments.

Comments

1

If I had to hazard a guess, I'd say it's because of this line:

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

I'm not sure exactly what signature (Func<string>)( () => "Hello, world!" ) will have, but it probably won't be the correct one (one accepting an implicit parameter of your defined type).

I'd recommend using the method builder's GetILGenerator method to do this:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.