-1

I am new to the Reflection.Emit API and have generated a bare minimum assembly with an entry point that returns an exit code based on a few simple I/O checks. The reason for creating an external assembly is that a piece of code needs to run outside the current process space and will be transient itself. It will eventually be deleted by the creating app.

Having said that, the code to be generated is quite complex and I would rather avoid creating a separate project for a transient assembly. I don't know IL enough to use the ILGenerator for this complex a method.

I have also read this SO question about using existing methods to generate IL and it does not seem possible short of parsing IL. I don't know of a way to take an existing method, detach it from the current context and add it to the new dynamic type. If such a way exists, that would be an acceptable answer to this post.

My final though is to have the generated assembly reference the generating assembly as a library. even though both assemblies are WinForms apps, is there a downside to referencing them as a library?

Community
  • 1
  • 1
Raheel Khan
  • 14,205
  • 13
  • 80
  • 168
  • 1
    Another option for dynamic code generation is the CodeDom API which allows you to compile C# on the fly. You can compile it directly from source text or use the object model. – Mike Zboray Jul 24 '14 at 05:52
  • Yes that's definitely an option. – Raheel Khan Jul 24 '14 at 06:02
  • 1
    Have you looked at `MethodRental`? http://msdn2.microsoft.com/en-us/library/system.reflection.emit.methodrental – leppie Jul 24 '14 at 06:38
  • @leppie: No I had not. Am trying the example and also trying to figure out how to extract bytes from the existing method. Thank you for the link! Seems like the closest to what I'm looking for. You should post this as an answer. – Raheel Khan Jul 24 '14 at 07:46
  • Would the down-voter care to leave a comment? – Raheel Khan Jul 24 '14 at 07:47
  • To get a method body is a `byte[]` you can do, `meth.GetMethodBody().GetILAsByteArray()` http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.getilasbytearray If you can make it work, post a small snippet as the answer (and mark it ;p) – leppie Jul 24 '14 at 09:04
  • @leppie: I created a new method with the same signature, made it simply return a hard coded Int32 value. The call to `MethodRental.SwapMethodBody` threw the following exception: `InvalidProgramException: CLR detected an invalid program`. This looks like the same issue the OP of my linked question faced. – Raheel Khan Jul 24 '14 at 09:56
  • Oh well, it was worth a try :) – leppie Jul 24 '14 at 10:38

1 Answers1

0

Finally solved it using Expression Trees instead of having to emit raw IL.

var queue = new Queue<Expression>();
var arguments = Expression.Parameter(typeof(string []), "args");

queue.Enqueue(Expression.Call(typeof(Console).GetMethod("WriteLine", new Type [] { })));

var block = Expression.Block(queue);
var lambda = Expression.Lambda<Func<string [], int>>(block, new ParameterExpression [] { arguments });

lambda.CompileToMethod(builderMethod);
// builderMethod is a MethodBuilder instance created earlier.

This is very powerful indeed and definitely suited for situations where micro-perf is not required using ILGenerator.

Raheel Khan
  • 14,205
  • 13
  • 80
  • 168