1

Reflection.Emit を使用してアセンブリを作成していますが、特別なコールバックを呼び出す必要があります。

コードの簡略版は次のとおりです。

public void Call(ILGenerator il, Delegate action)
{
    il.Emit(OpCodes.Call, action.Method);
}

public static void DoStuff()
{
    Console.WriteLine("Action invoked!");
}

Call(CurrentMethod.ILGenerator, DoStuff);

このコードは期待どおりに機能します。

ただし、次のようにラムダ式を渡したいです。

Call(CurrentMethod.ILGenerator, () => Console.WriteLine("test"));

今回は、次の例外がスローされます。

System.MethodAccessException : メソッド '.Run()' によるメソッド 'Compiler.Test.ImportedFunctions.b__0()' へのアクセスに失敗しました。

それを回避する方法はありますか?

4

1 に答える 1

1

Delegateあまりにも一般的です。試してみてくださいAction

ただし、注意してください。

デリゲートのターゲットプロパティがnullでない場合、これは不可能です。

ターゲットの値を静的フィールドに一時的に保存することで、これを回避できます。

考えられる解決策(モディファイアの放出):

class Foo { static object target; }

public void Call(ILGenerator il, Action action)
{
    Foo.target = action.Target;
    il.Emit(OpCodes.Ldsfld, typeof(Foo).GetField("target");
    il.Emit(OpCodes.Callvirt, action.Method);
}

再帰呼び出しのないシングルスレッド環境で実行する場合、これは機能します。

Foo.target再帰的な環境では、C#では使用できない動的バインディングを使用する必要があります。

幸いなことに、私はすでにC#用にそのような機能を作成しました。

于 2013-03-20T17:37:48.593 に答える