0

HTTP を使用して JSON RPC インターフェイス経由でXBMCと通信するために、C# で .NET ライブラリをコーディングしています。

暫定バージョンをコーディングしてリリースしましたが、すべてが同期的に行われます。次に、 WP7 用の XBMC リモートを構築していた/構築しているため、ライブラリを独自の目的で非同期になるように再コーディングしました。

私は今、新しい非同期ライブラリをリリースしたいと思っていますが、リリースする前にそれがきちんと整頓されていることを確認したいと思っています。

非同期の性質により、ユーザーはリクエストを開始し、デリゲートに一致するコールバック メソッドを提供し、受信したレスポンスを処理します。

私が抱えている問題は、ライブラリ内でリクエストの存続期間中 RequestState オブジェクトを追跡することです。これには、http リクエスト/レスポンスとユーザーコールバックなどがメンバー変数として含まれています。これは、1 つのタイプのオブジェクトのみであれば問題ありません。戻ってきていましたが、ユーザーの呼び出しに応じて、曲のリストや映画のリストなどが返される場合があります.

現時点での私の実装では、単純なオブジェクトである単一のパラメーターを持つ単一のデリゲート ResponseDataRecieved を使用しています。これは私だけが使用しているため、どのメソッドが何を返し、いつ応答を処理するかを知っています。それは本当にです-リスト、リストなど

ただし、サードパーティがこれを行う必要はありません。デリゲート署名には、正しいタイプのオブジェクトが含まれている必要があります。したがって、サードパーティに返すことができるすべてのタイプの応答データに対してデリゲートが必要です-具体的な問題は、これを内部で適切に処理する方法です-それぞれが異なるメンバー変数を持つさまざまな RequestState オブジェクトがたくさんありますか?さまざまな代表のために?それは正しく「感じ」ません。これを優雅かつきれいに行う方法がわかりません。

4

2 に答える 2

0

最初に頭に浮かぶのはジェネリックです。ResponseDataRecieved<T>ここで、T はコールバックで期待される型です。ただし、コールバックをキャプチャされた変数として保存できます。例えば:

public delegate void CallBackA(int i);
public delegate void CallBackB(string s);

public class RequestHandler
{
    public void QueueRequestA(CallBackA callback)
    {
        Task.Factory.StartNew(() =>
                                  {
                                      int ret = 0;
                                      //ret = get stuff of type A from server
                                      callback(ret); //callback is captured here
                                  });
    }

    public void QueueRequestB(CallBackB callback)
    {
        Task.Factory.StartNew(() =>
                                  {
                                      string str = "";
                                      //str = get stuff of typw B from server
                                      callback(str); //callback is captured here
                                  });
    }
}
于 2011-01-03T08:56:01.017 に答える
0

私の理解が正しければ、複数のメソッドを提供するインターフェイスがあり、それぞれが基本的に同じ種類のデリゲートを受け取りますが、入力として異なる型のパラメーターを取得します。このようなもの:

GetListOfSongs(..., delegate(List<Song> result) { ... });
GetListOfMovies(..., delegate(List<Movie> result) { ... });

インターフェイスのメソッドと一緒に現れ始めるデリゲート シグネチャについて心配していませんか?

その場合は、ジェネリックが探しているものです。実際、デリゲート シグネチャが私の例と一致する場合、つまり、1 つの入力パラメーターを受け入れ、値を返さない場合、必要なデリゲート型は BCL に既に存在します。と呼ばれていAction<T>ます。上記のメソッドを次のように宣言できます。

GetListOfSongs(..., Action<List<Song>> callback);
GetListOfMovies(..., Action<List<Movie>> callback);

デリゲート タイプは 1 つしかありません。つまり、Action<T>.

これで、複数のパラメーターを渡す必要がある場合でも、カバーされます。最大 16 個の入力パラメーター用の Action のバージョンが存在します (ただし、それらの署名は少し派手に見え始めます: Action<T1, T2, T3 ...>)。

インフラストラクチャ内のどこかで使用する値もコールバックに返すようにしたい場合Func<T, TResult>は、あなたの友人です (T は入力パラメーターの型であり、TResult はデリゲートから返される値の型です)。

おまけとして、インターフェイスで公開しないことをお勧めList<T>します。すべてのクライアントでリスト操作が必要になると本当に考えている場合は、 を使用しますが、そうでない場合でも or をIList<T>検討してください。ICollection<T>IEnumerable<T>

于 2011-01-02T11:43:46.567 に答える