Viewing the IL code generated from a compiled expression
Asked Answered
B

3

34

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?

Bolometer answered 21/1, 2011 at 22:0 Comment(3)
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?Marciamarciano
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.Bolometer
Have you tried with the great LinqPad tool ? linqpad.net With it you can display generated code as MSIL and experiment quickly almost anything...Armipotent
P
32

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.

Plot answered 21/1, 2011 at 22:48 Comment(5)
Eric, if you have the time, could you flesh this out into a more substantial answer? Link only answers are discouraged on Stack Overflow.Filth
Too bad it isn't compilable, is there a binary version available?Tome
@casperOne: I encourage you to do so. I have nothing to add.Plot
@JeroenvanLangen: I haven't the faintest idea. I suggest that you address your question to its author.Plot
@EricLippert: Tyvm for your reaction, I solved this by saving it to an assmebly and using a reflector/ilspy. Tnx again.Tome
C
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");
Centralize answered 21/1, 2011 at 22:56 Comment(2)
in case anyone interested in remove the MethodAttributes.Static from DefineMethod method, there are some research I got https://mcmap.net/q/451570/-lambdaexpression-compiletomethod in conclusion, CompileToMethod only works with static methodBrunhilde
also it doesn't work if you have Expression.Constant that capture some live objectsCapriole
Y
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.

Yale answered 16/8, 2020 at 23:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.