11

ちょっとした目新しさとして、実行時に生成された軽量コードとVSコンパイラによって生成されたコードとのILの外観がどのように異なるかを確認しようとしています。これは、VSコードが次のような異なるパフォーマンスプロファイルで実行される傾向があることに気付いたためです。キャスト。

だから私は次のコードを書きました::

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

残念ながら、GetMethodBodyは明らかに式ツリーによって生成されたコードに対する不正な操作であるため、これは例外をスローします。ライブラリ方式で(つまり、ツールにAPIがない限り、外部ツールを使用しないで)軽量codegenを使用してコードによって生成されたコードを確認するにはどうすればよいですか?

編集:エラーは5行目で発生します。compiled.Method.GetMethodBody()は例外をスローします。

Edit2:メソッドで宣言されたローカル変数を回復する方法を知っている人はいますか?または、GetVariablesにアクセスする方法はありませんか?

4

4 に答える 4

17

ええ、機能しません。メソッドはReflection.Emitによって生成されます。ILは、MethodBuilderのILGeneratorに保存されます。あなたはそれを掘り出すことができますが、あなたはかなり必死でなければなりません。内部メンバーとプライベートメンバーに到達するには、熟考が必要です。これは.NET3.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>
        //...

.NET 4.0では、ILジェネレーターが変更されたため、ilgen.GetType()。BaseType.GetField(...)を使用する必要があります。DynamicILGeneratorはILGeneratorから派生しています。

于 2010-11-10T17:20:24.797 に答える
2

ここのILReaderは機能するはずです。

ILVisualizer2010ソリューション

于 2012-02-20T19:20:00.767 に答える
0

ハンス・パッサントの仕事に基づいて、私はもう少し深く掘り下げることができました。あなたが呼び出すべきメソッドがあるようです。BakeByteArrayそれは次のように呼ばれます。

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[];

これは確かに役立ちますが、VariableInfo'sまだ解決する方法がありません。これは私の仕事に役立つものです。

于 2010-11-10T18:45:46.957 に答える
0

ここでの現在のソリューションは、.NET4の現在の状況にうまく対処していません。DynamicILInfoまたはを使用して動的メソッドを作成できますが、ここにリストされているソリューションは動的メソッドILGeneratorはまったく機能しません。DynamicILInfo

DynamicILInfoILを生成する方法を使用するか、その方法を使用するかにかかわらずILGenerator、ILバイトコードはで終わりますDynamicMethod.m_resolver.m_code。両方の方法を確認する必要はなく、それほど複雑ではありません。

これは、使用する必要があるバージョンです。

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

より多くのヘルパーメソッドとDynamicMethodトークン解決の問題の解決策については、この回答を参照してください。

于 2016-02-29T23:03:14.477 に答える