2012-12-05 8 views
18

C#のどのオブジェクトでも、静的に定義された(「静的」という意味で「コンパイル時に決定」という意味で「クラスレベルメンバ」という意味ではなく)メソッドを動的に呼び出す場合は、クラスが露出していないに応答インスタンスメソッドはTryInvokeMemberを使用して呼び出し、動的メソッドしかし、オブジェクトが(未定義)するDynamicObject応答から継承して動的に動的オブジェクトのメソッドを動的に呼び出すにはどうすればよいですか?

typeof(Foo).GetMethod("Bar").Invoke(foo, new object[] { /* params */ }); 

を:その方法へのハンドルを取得し、それを呼び出すために反射明白な理由から、反射を通して。これは、応答するメソッドのメソッドハンドルをTryInvokeMemberで取得できないことを意味します。

逆説的に、dynamicオブジェクトの動的メソッドを、dynamicオブジェクトで定義されたメソッドと同じように簡単に呼び出すことはできないようです。

私はTryInvokeMemberを直接呼び出すと考えましたが、最初の引数は抽象クラスInvokeMemberBinderのインスタンスでなければなりません。私は、動的オブジェクト上で動的メソッドを呼び出すクラスを実装する必要がある場合は、何か間違っている必要があります。

私はターゲットクラスが はそれを実装し、それが TryInvokeMemberを使用して対応する必要があることをしないということ?知って、その名前で dynamicオブジェクトのメソッドを呼び出すことができますどのように

答えて

9

C#コンパイラが動的オブジェクトのメソッド呼び出しのために出力するものを模倣する方法の1つです。これには、Microsoft.CSharp.RuntimeBinder名前空間に[EditorBrowsable(EditorBrowsableState.Never)]と表示された種類の束を使用する必要があります。そのため、Intellisenseでは表示されません。言うまでもなく、これはサポートされているシナリオのようには見えないので、自己責任で使用してください!

このコードはDynamicObjectから派生したクラスのインスタンスで引数なしダイナミックBarメソッドを呼び出します。

dynamic dynamicObject = new DerivedFromDynamicObject(); 
var callSiteBinder = Binder.InvokeMember(CSharpBinderFlags.None, "Bar", Enumerable.Empty<Type>(), typeof(Program), 
    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); 
var callSite = CallSite<Action<CallSite, object>>.Create(callSiteBinder); 
callSite.Target(callSite, dynamicObject); 

Thisブログの記事とthis oneコールサイトやバインダーの詳細血みどろの詳細を持っています。

+0

楽しい音。私は誰かが実際にサポートされている解決策を持っているかどうかを確認するのを待つつもりです。 – zneak

+1

一方、それはコンパイラがすでに行っていることなので、今日構築された 'dynamic'を使っているアプリケーションを殺すことはないので、動作を止めることはまずありません。 – zneak

+0

@zneakそれはかなり安全だと思うでしょう。型が隠されていることを保証するほどの長さになったのは単なる驚くべきことです。 – Trillian

14

ダイナミックバインダーコードをカプセル化するダイナミック(ダイナミック)(ダイナミック(nugetで利用可能))フレームワークがあります。これには、コールサイトが自動的にキャッシュされます。バインダーのすべてのタイプ(ゲッタ、セッター、イベント、インデクサー、演算子、コンバージョン)にも便利なメソッドがありますが、具体的にはInvokeMemberが必要です。

ダイナミックバインダーコードは、クラスの静的に定義された(コンパイル時に)メンバーを呼び出すとき、実際にはリフレクション(償却)よりも高速に実行されます。

Dynamic.InvokeMember(foo,"Bar",arg...); 
+0

それはかなりクールに見えます! – zneak

+0

男!素晴らしいナゲット!完璧に動作します! ありがとうございました!答えとしてマークする必要があります! – CodeHacker

+0

偉大なパッケージは、仕事を終えてください。 – Andro

関連する問題