18

C# の任意のオブジェクトで、静的に定義された (「クラス レベルのメンバー」という意味ではなく、「コンパイル時に決定される」という意味で「静的に」) メソッドを動的に呼び出したい場合は、リフレクションを使用してそのメソッドへのハンドルを取得して呼び出します。

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

DynamicObjectただし、を使用して応答する (未定義の) インスタンス メソッド呼び出しから継承することによって動的に作成されたオブジェクトTryInvokeMemberと、クラスが応答する動的メソッドは、明らかな理由により、リフレクションによって公開されません。これは、 によって応答されるべきメソッドのメソッド ハンドルを取得できないことを意味しTryInvokeMemberます。

皮肉なことdynamicに、非オブジェクトで定義済みメソッドを呼び出すのと同じくらい簡単に、オブジェクトで動的メソッドを動的に呼び出すことはできないように思えdynamicます。

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

dynamicオブジェクトのメソッドをその名前で呼び出すにはどうすれよいTryInvokeMemberですか?

4

2 に答える 2

15

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

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

Dynamic.InvokeMember(foo,"Bar",arg...);
于 2012-12-10T16:09:06.490 に答える
9

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

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

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);

このブログ投稿とこれには、通話サイトとバインダーに関する詳細が含まれています。

于 2012-12-05T02:42:20.210 に答える