2011-01-21 9 views
28

¿Es posible ver el código IL generado al llamar a Compile() en un árbol de Expresión? Considere este ejemplo muy simple:Visualización del código IL generado a partir de una expresión compilada

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; 
    } 
} 

Ahora, el árbol de expresión hace lo que la última línea de Main dice. Compila la aplicación, luego ábrela en Reflector. Puede ver el código IL de p.Value = 5; que hace la asignación. Pero el árbol de expresiones se creó y compiló en tiempo de ejecución. ¿Es posible ver el código IL resultante de la compilación?

+0

hacer lo que desea el equivalente * * IL por lo que están haciendo * * (es decir, el establecimiento de una propiedad)? ¿O hay algo sobre la salida 'Expression' que le interesa específicamente? –

+0

Nada específico. Me gusta mirar el código IL de vez en cuando. Pero con expresiones puedes hacer un método que no obtenga IL en el ensamblado compilado. El IL solía * crear * ese árbol de expresión está allí, pero no es el resultado de la compilación del árbol de expresión. ¿Tiene sentido? Esto es simplemente una curiosidad y no tiene ningún propósito práctico real que pueda ver. – Amy

+1

¿Has probado con la gran herramienta ** LinqPad **? http://www.linqpad.net/ Con él puede mostrar el código generado como MSIL y experimentar rápidamente casi cualquier cosa ... – AFract

Respuesta

28

Sí! Utilice esta herramienta:

http://blogs.msdn.com/b/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx

Esto fue increíblemente útil cuando estaba poniendo en práctica y depuración de compilación, como estoy seguro de que se pueda imaginar.

+3

Eric, si tiene tiempo, ¿podría darle más importancia a esta pregunta? Las respuestas de enlace único se desaconsejan en Stack Overflow. – casperOne

+0

Lástima que no es compilable, ¿hay una versión binaria disponible? –

+2

@casperOne: te animo a que lo hagas. No tengo nada que añadir. –

21

Cree un DynamicAssembly, luego un DynamicModule, DynamicType y DynamicMethod. Haga público y estático ese método y páselo al método CompileTo() en el lambda. Cuando haces que el conjunto lo señale como Guardar. Luego llame al método Save() y pase una ruta. Será escrito en el disco. Pop abierto en reflector.

Algo así como:

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"); 
+0

en caso de que alguien esté interesado en eliminar 'MethodAttributes.Static' del método' DefineMethod', hay algunas investigaciones que obtuve http://stackoverflow.com/a/3993023/903505 en conclusión, 'CompileToMethod' solo funciona con static método – Ariex

Cuestiones relacionadas