Frage

Als bisschen eines Novum, ich versuche, wie unterschiedlich die IL aus leichtem Code zur Laufzeit sieht vs Code durch die VS-Compiler erzeugt erzeugt, um zu sehen, wie ich, dass VS Code bemerkte dazu neigt, mit einem anderen Leistungsprofil zu laufen für Dinge wie Abgüsse.

So schrieb ich den folgenden Code ::

Func<object,string> vs = x=>(string)x;
Expression<Func<object,string>> exp = x=>(string)x;
var compiled = exp.Compile(); 
Array.ForEach(vs.Method.GetMethodBody().GetILAsByteArray(),Console.WriteLine);
Array.ForEach(compiled.Method.GetMethodBody().GetILAsByteArray(),Console.WriteLine);

Leider wirft dies eine Ausnahme als GetMethodBody ist offenbar eine illegale Operation Code durch Expression Bäume erzeugt. Wie kann ich in einer Bibliothek Weise (das heißt nicht mit einem externen Tool, wenn das Werkzeug eine API hat) Blick auf dem Code mithilfe von Code leichte codegen erzeugt?

Edit: der Fehler in Zeile 5 auftritt, compiled.Method.GetMethodBody () wirft die Ausnahme.

Edit2: Wer weiß, wie die lokalen Variablen in der Methode deklariert erholen? Oder gibt es keine Möglichkeit zu GetVariables?

War es hilfreich?

Lösung

Ja, nicht funktioniert, wird das Verfahren durch Reflection.Emit erzeugt. Die IL ist in der Method des ILGenerator gespeichert. Sie können es ausgraben, aber sie ziemlich verzweifelt sein müssen. Reflexion ist notwendig, um die inneren und private Mitglieder zu bekommen. Das funktioniert auf .NET 3.5SP1:

using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
...

        var mtype = compiled.Method.GetType();
        var fiOwner = mtype.GetField("m_owner", BindingFlags.Instance | BindingFlags.NonPublic);
        var dynMethod = fiOwner.GetValue(compiled.Method) as DynamicMethod;
        var ilgen = dynMethod.GetILGenerator();
        var fiBytes = ilgen.GetType().GetField("m_ILStream", BindingFlags.Instance | BindingFlags.NonPublic);
        var fiLength = ilgen.GetType().GetField("m_length", BindingFlags.Instance | BindingFlags.NonPublic);
        byte[] il = fiBytes.GetValue(ilgen) as byte[];
        int cnt = (int)fiLength.GetValue(ilgen);
        // Dump <cnt> bytes from <il>
        //...

Auf .NET 4.0 Sie verwenden müssen ilgen.GetType (). BaseType.GetField (...), weil der IL-Generator geändert wurde, DynamicILGenerator, von ILGenerator abgeleitet.

Andere Tipps

Die ILReader hören sollte funktionieren.

ILVisualizer 2010-Lösung

http://blogs.msdn.com/ b / haibo_luo / Archiv / 2010/04/19 / 9998595.aspx

Basierend off Hans Passant Arbeit konnte ich ein wenig tiefer graben, scheint es eine Methode zu sein, dass Sie anrufen sollen, genannt BakeByteArray so folgenden Arbeiten ::

var dynMethod = fiOwner.GetValue(compiled.Method) as DynamicMethod;
var ilgen =dynamicMethod.GetILGenerator();
byte[] il = ilgen.GetType().GetMethod("BakeByteArray", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(ilgen, null) as byte[];

Das hilft natürlich, aber ich habe noch keine Möglichkeit, zu lösen VariableInfo's nur noch das etwas ist, das in meiner Arbeit helfen würde.

Die aktuellen hier Lösungen sind nicht die aktuelle Situation in .NET 4 sehr gut Adressierung. Sie können entweder DynamicILInfo oder ILGenerator verwenden, um die dynamische Methode zu schaffen, aber die aufgeführten Lösungen hier nicht Arbeit mit DynamicILInfo dynamischen Methoden bei allen .

Ob Sie die DynamicILInfo Methode von IL zu erzeugen oder die ILGenerator Methode, der IL-Bytecode endet in DynamicMethod.m_resolver.m_code . Sie müssen nicht beide Methoden überprüfen und es ist eine weniger komplexe Lösung.

Dies ist die Version, die Sie verwenden sollen:

public static byte[] GetILBytes(DynamicMethod dynamicMethod)
{
    var resolver = typeof(DynamicMethod).GetField("m_resolver", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dynamicMethod);
    if (resolver == null) throw new ArgumentException("The dynamic method's IL has not been finalized.");
    return (byte[])resolver.GetType().GetField("m_code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(resolver);
}

Sehen Sie diese Antwort für weitere Hilfsmethoden und eine Lösung für die Dynamic Token Auflösung Ausgabe.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top