2

私は次のクラスを持っています:

public class TestClass
{   
    public static readonly string HELLO = "Hello, ";

    public static string SayHello(string name)
    {
        return HELLO + name;
    } 
}

そして、DynamicMethodを介してHELLOの静的フィールドにアクセスしたいと思います。GetValueを使用した標準のリフレクションは機能します。

public static string GetViaInvoke()
    {
        Type tcType = typeof(TestClass);
        FieldInfo fi = tcType.GetField("HELLO");
        string result = fi.GetValue(null) as string;
        return result;
    }

しかし、私は次のようなものが必要です(OpCodesは同様のメソッドのILDasmから来ています):

public static string GetViaDynamicMethod()
    {
        Type tcType = typeof(TestClass);
        FieldInfo fi = tcType.GetField("HELLO");

        DynamicMethod dm = new DynamicMethod("getHello", typeof(string), Type.EmptyTypes);            
        ILGenerator iL = dm.GetILGenerator();

        iL.DeclareLocal(typeof(string));
        iL.Emit(OpCodes.Nop);
        iL.Emit(OpCodes.Ldsfld, fi);
        iL.Emit(OpCodes.Stloc_0);
        iL.Emit(OpCodes.Br_S, 0x09);
        iL.Emit(OpCodes.Ldloc_0);
        iL.Emit(OpCodes.Ret);

        Func<string> fun = dm.CreateDelegate(typeof(Func<string>)) as Func<string>;
        string result = fun();
        return result;
    }

アイデアは非常に単純で、動的メソッドは非静的フィールド(ldfldオペコードとこのオブジェクト)で正常に機能しますが、静的フィールドにアクセスしようとすると例外が発生します。

System.InvalidProgramException was unhandled
  Message=InvalidProgramException
4

1 に答える 1

2

同じことを行う逆コンパイルされたコードに基づいて書くILコードは良い考えですが、それでも自分が何をしているのかを理解する必要があります。

のドキュメントをBr_S見ると、Labelではなく、で使用することになっていることがわかりますint。コード内のはバイトオフセット9の命令に分岐すると思いますが、Br_Sどの命令であるかわかりません。このようなコードを記述しないでください。

静的フィールドの値をロードして返すだけの場合は、ローカル変数やブランチは必要ありません。以下で十分です。

iL.Emit(OpCodes.Ldsfld, fi);
iL.Emit(OpCodes.Ret);

これは、評価スタックに値をロードし、すぐに戻るということです。値を返すメソッドから戻る場合、評価スタックにある単一の値がその戻り値として使用されるため、これは機能します。

于 2012-07-12T17:18:10.037 に答える