2

で実行時に独自の関数を作成して CIL を学習していますReflection.Emit。今までのやり方がいかに簡単だったかには実際に驚いていますが、自分のやり方を推測できない何かにぶつかり、ドキュメントに関連するものは何も見つかりません。

定義した非常に単純なクラスを単純に出力する関数を作成しようとしています。たとえば、コードを print strings に変更すると動作しますが、 class のインスタンスを渡すと常に実行に失敗しますA

奇妙なのは、関数本体をコメントアウトできることTargetInvocationExceptionです。それは非常に単純でなければなりませんが、何が起きているのかわかりません!

class A
{
    public override string  ToString()
    {
        return "AAA!";
    }
}

class Program
{
    static void Main(string[] args)
    {
        DynamicMethod func = new DynamicMethod("func", null, new Type[] { typeof(A) });

        ILGenerator il = func.GetILGenerator();

        //il.Emit(OpCodes.Ldarg_0);
        //il.Emit(OpCodes.Box, typeof(A));
        //il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(A) }));

        il.Emit(OpCodes.Ret);

        func.Invoke(null, new object[] { new A() });

        Console.Read();
    }
}

これを例外として発生させるには、何が間違っているのでしょうか? これが私のクラスでのみ発生するのはなぜですか?

4

3 に答える 3

1

それは実際にはかなりばかげていました。私はこれに数時間を費やしましたが、Laurent Etiemble のアドバイスに従ってデリゲートを作成したところ、クラス A が公開されていないという例外が表示されました。

解決策: の前に public キーワードを追加しclass Aます。完璧に動作します。私はそれが非常に単純なものでなければならないことを知っていました.

于 2010-02-08T22:31:01.227 に答える
0

まず、クラスであり、ボックス化する必要がないため、Boxオペコードを発行するべきではありません。Aボクシングは値型専用です。

2 番目 - 失敗する理由は、メソッドがクラス A にアクセスする権限を持っていない (公開されていない) ためです。makeまたはこのコンストラクターを使用し、skipVisibility パラメーターに渡すことで、A public可視性チェックをスキップするように JIT コンパイラーに指示できます。true

于 2010-02-08T22:18:19.480 に答える
0

問題は単純ですが、自明ではありません。まず、すでに指摘したように、引数をボックス化しないでください。しかし、本当の問題は、A クラスが公開されていないことです。(完全な関数ではなく) 使用している Invoke 関数の既定のバインドは、パブリック メソッドのみを検索することです。A は非公開クラスであるため、関数を見つけることができず (驚くべきことに)、失敗することを意味します。

于 2010-02-08T22:31:28.370 に答える