1

呼び出し可能な「動的」タイプのオブジェクトがある状況があります。一連の引数を使用して、実行時にオブジェクトを動的に呼び出す関数を実装しようとしています。コンパイル時に引数の数がわかっている場合は、簡単に呼び出すことができます。

Object StaticInvoke(dynamic func, Object[] args) {
    // arguments are explicitly unwrapped and bound to the invokation
    // requiring that we know the number at compile time
    return func(args[0], args[1], ...); 
}

しかし、args 配列は可変長である可能性があるため、これは私が望むものを達成しません。任意の数の引数をサポートする方法がわかりません。私が思いついた最も近いものは次のようなものです:

static Object Invoke(dynamic func, Object[] args)
{

    // not sure what to put here
    switch(args.Length)
    {
        case 0:
            return func();
        case 1:
            return func(args[0]);
        case 2:
            return func(args[0], args[1]);
        ...
        default:
            throw new NotSupportedException();
    }
}

これにより、渡すことができる引数の数が制限されます。私はこの制限に耐えることができると思いますが、私がやろうとしていることは可能であるべきだと感じています.

基本的に、C# で JavaScript の「適用」機能を実装しようとしています。私がやろうとしていることを達成するためのより簡単な方法はありますか? 明らかな何かが欠けているように感じます。

4

2 に答える 2

1

オープンソース Apache ライセンスの ImpromptuInterface (ナゲット上) には、これを行う静的メソッドImpromptu.Invokeがあります。実装を見ると、任意の数の引数を処理できますが、名前付き引数を動的に記述して呼び出すメカニズムを提供するなど、おそらく必要のない機能もあります。

スイッチケースのアイデアは、シンプルで高速であるべきであるため、使用方法によっては実際に進むべき道かもしれません.

switch ケースでは、N がサポートする引数の最大数であり、C# コンパイラは N+1 コールサイトを作成し、それらがどこにあるかを静的に認識します。Impromptu は、コンパイラと同じように dlr API を呼び出しますが、呼び出しサイトをハッシュテーブルに格納するため、ルックアップ時間が追加されます (悪くはありません)。

dlr API には、呼び出している番号または引数と一致する署名を持つデリゲートも必要です。コンパイラは静的に N+1 のデリゲートがあることを確認しますが、Impromptu はスイッチで 17 の組み込み Func<> を使用します。ケースを作成し、必要に応じて新しいデリゲートの発行を開始すると、生成するのに一度だけ大きなコストがかかり、その後の呼び出しのためにハッシュテーブルのルックアップが追加されます。

于 2012-04-18T15:32:24.967 に答える
0

編集:これは答えではありません-@Markが探しているものではないことを他の人に知らせるためにここに置いておきます。

通常のオブジェクトの場合は、次を使用しますMethodBase.InvokeMethod

 MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
 object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});
于 2012-04-17T17:58:26.457 に答える