3

私にはアイデアがありますが、それを実装するための支援が必要です。

WCFは、契約でデリゲートをサポートしていません。代わりに、面倒なコールバックコントラクトメカニズムがあり、この制限を克服する方法を探しています。

IDataContractSurrogateコントラクト内の各デリゲートを、リモートエンドポイントにシリアル化されるトークンに置き換えるためにを使用することを考えました。そこで、トークンは生成されたデリゲートに逆シリアル化されます。この生成されたデリゲートは、(デリゲートが呼び出された)すべての引数をカプセル化する汎用コールバックメッセージを送信します。

ジェネリックコールバックメッセージは最初のエンドポイントに到達し、そこで元のデリゲートが引数を使用して呼び出されます。

目的の(簡略化された)シーケンスは次のとおりです。

  1. AはB-proxy.Foo(callback)を呼び出します
  2. コールバックはDelegateSurrogateを介してシリアル化されます。
  3. DelegateSurrogateは、デリゲートを専用のデリゲートストレージに格納し、トークンに置き換えます
  4. メッセージはBのエンドポイントに到着します
  5. トークンはDelegateSurrogateを介して逆シリアル化されます
  6. DelegateSurrogateは、生成されたデリゲートを構築します
  7. B.Foo(generatedCallback)が呼び出されます
  8. 後で、BはgeneratedCallback(args)を呼び出しています
  9. generateCallback(args)は、Aのエンドポイントで専用のジェネリックコントラクトを呼び出します:CallbackContract-proxy.GenericCallback(args)
  10. CallbackContract.GenericCallback(args)がAのエンドポイントで呼び出されます
  11. 元のコールバックがストレージから取得され、呼び出されます:callback(args)

以前にサービスバス(NServiceBus)を使用してこれを実装しましたが、このアイデアをWCFに適合させたいので、苦労しています。手順3、6、9、および11を実装する方法を知っています。WCFのすべて(特に代理部分)を配線する方法はまだわかりません。

それだけです-私の質問が理にかなっていて、ここでの集合的な知恵が私がこれを構築するのを助けることができることを願っています。

これが私の希望するソリューションの使用例です。

// client side
remoteSvc.GetEmployeeById(17, emp => 
{
    employees.Add(emp);
    logger.log("Result received");
});

// server side
public void GetEmployeeById(int id, Action<Employee> callback)
{
    var emp = getEmpFromDb(id);
    callback(emp);
}
4

1 に答える 1

2

実際、このシナリオでは、ExpressionAPIを調べます。デリゲートとは異なり、Expression実行時に分解できます。デフォルトではそれらをシリアル化することはできませんが、そのスペースで多くの作業が行われています。また、WCFデータサービスなど、多くのLINQプロバイダーがバックグラウンドで実行することにも少し似ています。

もちろん、別のアプローチは、RPCのフックとしてラムダ式を使用することです。これをここで説明します。これを実装するコードは、protobuf-netツリーで無料で入手できます。属性を使用してトークンをメソッドに関連付け、から属性を取得することで、これをカスタマイズできますMethodInfo

IMO、デリゲートの問題は、デリゲートが実装に緊密に結合されているため、両端で異なる実装を持つことができないことです(これは一般的な要件です)。

式には、ラムダが引き続きインテリセンスなどをサポートするという利点があるため、次のようなことができます。

client.Invoke(svc => svc.Foo(123, "abc"));

Fooそして、そこから(MethodInfo)、123、および「abc」を個別に取得します。これには、キャプチャされた変数、 ref/outなどが含まれます。すべて機能します。

于 2010-07-10T09:35:10.077 に答える