33

Is it possible to view the IL code generated when you call Compile() on an Expression tree? Consider this very simple example:

class Program
{
    public int Value { get; set; }

    static void Main(string[] args)
    {
        var param = Expression.Parameter(typeof(Program));
        var con = Expression.Constant(5);
        var prop = Expression.Property(param, typeof(Program).GetProperty("Value"));
        var assign = Expression.Assign(prop, con);
        Action<Program> lambda = Expression.Lambda<Action<Program>>(assign, param).Compile();

        Program p = new Program();
        lambda(p);



        //p.Value = 5;
    }
}

Now, the expression tree does what the last line of Main says. Compile the application, then open it in Reflector. You can see the IL code of p.Value = 5; that does the assignment. But the expression tree was made and compiled at runtime. Is it possible to view the resulting IL code from the compile?

  • Do you just want the *equivalent* IL for what you are *doing* (i.e. setting a property)? Or is there something about the `Expression` output that you are specifically interested in? – Marc Gravell Jan 21 '11 at 22:03
  • Nothing specific. I like looking at the IL code from time to time. But with expressions you can make a method that doesn't get any IL in the compiled assembly. The IL used to *create* that expression tree is there, but not the result of the expression tree's compile itself. Does that make sense? This is simply a curiosity and doesn't serve any real practical purpose that I can see. –  Jan 21 '11 at 22:08
  • 1
    Have you tried with the great **LinqPad** tool ? http://www.linqpad.net/ With it you can display generated code as MSIL and experiment quickly almost anything... – AFract Jan 21 '11 at 22:48

3 Answers3

30

Yes! Use this tool:

https://github.com/drewnoakes/il-visualizer

This was incredibly useful when I was implementing and debugging Compile, as I'm sure you can imagine.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
25

Create a DynamicAssembly, then a DynamicModule, DynamicType and DynamicMethod. Make that method public and static and pass it to the method CompileTo() on the lambda. When you make the assembly flag it as Save. Then call the Save() method and pass a path. It will be written to disk. Pop it open in reflector.

Something like:

var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
    new AssemblyName("dyn"), // call it whatever you want
    AssemblyBuilderAccess.Save);

var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll");
var dt = dm.DefineType("dyn_type");
var method = dt.DefineMethod(
    "Foo", 
    MethodAttributes.Public | MethodAttributes.Static);

lambda.CompileToMethod(method);
dt.CreateType();

da.Save("dyn.dll");
Ani
  • 111,048
  • 26
  • 262
  • 307
justin.m.chase
  • 13,061
  • 8
  • 52
  • 100
  • 1
    in case anyone interested in remove the `MethodAttributes.Static` from `DefineMethod` method, there are some research I got http://stackoverflow.com/a/3993023/903505 in conclusion, `CompileToMethod` only works with static method – Ariex Sep 19 '16 at 00:47
0

One of the greatest tools that I have come across online is SharpLab.io and it can do multiple tasks like generating IL, JIT codes, or can verify. It also supports syntax tree.

ihimv
  • 1,308
  • 12
  • 25