2012-04-17 19 views
1

私は、「ダイナミック」タイプのオブジェクトを呼び出すことができます。私は実行時に引数のセットでオブジェクトを動的に呼び出す関数を実装しようとしています。これは、args配列は、変数の長さにすることがなかったので、私が欲しいものを達成していない、C#で動的オブジェクトを呼び出すことは可能ですか?

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], ...); 
} 

しかし:私がコンパイル時に引数の数を知っていれば、それを呼び出すために十分に簡単です。私は任意の数の引数をサポートする方法を理解できません。私が一番近づいたのは、次のようなものです:

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の "apply"関数を実装しようとしています。私がやろうとしていることを達成するための簡単な方法はありますか?私は何かが明らかに欠けているように感じる。

+1

なぜあなたのコードのユーザは 'func(...) 'を直接呼び出すのではなく、' Invoke'を呼び出すのですか? –

+0

私はあなたが反射を使ってやろうとしていることをするための方法が組み込まれていると思うが、私はその分野の専門家ではない。代わりに、C#で可変数の引数を使いたい場合は、 'params'キーワードを見てください。私の免責事項は、あなたが実際に 'params'を望んでいるとは思わないということです、あなたはリフレクションを使ってメソッドを呼びたいと思っています。 –

+0

@ M.Babcock:私が作成しようとしている "invoke"は、私たちが使っている古いスクリプトエンジンの "レガシー"呼び出しと同じように、新しい動的呼び出しを扱えるようにインタフェースメソッドを実装しています。 – MarkPflug

答えて

1

オープンソースのApacheは(nuget上)ImpromptuInterfaceのライセンスを取得し、これを行う静的メソッドImpromptu.Invokeを持っています。実装を見ると、任意の数の引数を扱うことができますが、名前付き引数を動的に記述して呼び出すメカニズムを提供するなどの必要はないでしょう。

あなたのスイッチケースの考え方は、実際にはあなたの使い方に依存しているかもしれませんが、シンプルで高速でなければなりません。

スイッチケースでは、サポートする引数の最大数がNであるため、C#コンパイラはN + 1コールサイトを作成し、その場所は静的に知っています。 Impromptuはコンパイラと同じようにdlr apisを呼び出していますが、look up time(悪いことではありません)を追加するのはstoring the callsite in a hashtableです。

また、dlr apiの代理人には、呼び出し元の番号と一致するシグネチャが必要です。コンパイラはN + 1代理人を静的に確保しますが、Impromptuでは17個の組み込みFunc < >をスイッチケースに入れてからstart emiting new delegates as neededにすると、生成に1回のコストがかかり、後続のコールでハッシュテーブルのルックアップを追加します。

+0

即興のものは、私が必要とするものを少し残酷に見えます。私はスイッチが十分に良いと思う。情報をありがとう! – MarkPflug

0

編集:これは答えではありません。@マークが探しているものはないと他の人に知らせるためにここに保管してください。

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

MethodInfo magicMethod = magicType.GetMethod("ItsMagic"); 
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100}); 
+0

いいえ。彼は 'IDynamicMetaObjectProvider'を使っています。 – SLaks

関連する問題