Est-il possible d'afficher le code IL généré lorsque vous appelez Compile () sur un arbre d'expression? Considérez cet exemple très simple:
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;
}
}
Maintenant, l'arbre d'expression fait ce que dit la dernière ligne de Main
. Compilez l'application, puis ouvrez-la dans Reflector. Vous pouvez voir le code IL de p.Value = 5;
cela fait la cession. Mais l'arbre d'expression a été créé et compilé à l'exécution. Est-il possible d'afficher le code IL résultant de la compilation?
Oui! Utilisez cet outil:
https://github.com/drewnoakes/il-visualizer
C'était incroyablement utile lorsque j'implémentais et déboguais Compile, comme vous pouvez certainement l'imaginer.
Créez un DynamicAssembly, puis un DynamicModule, DynamicType et DynamicMethod. Rendez cette méthode publique et statique et transmettez-la à la méthode CompileTo () sur le lambda. Lorsque vous faites l’assemblage, marquez-le en tant que Save. Appelez ensuite la méthode Save () et transmettez un chemin. Il sera écrit sur le disque. Pop-le ouvert dans le réflecteur.
Quelque chose comme:
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");