13

Reactive Extensions(Rx)の適切なユースケースに頭を悩ませようとしています。引き続き発生する例は、UIイベント(ドラッグアンドドロップ、描画)、およびRxがWebサービス呼び出しなどの非同期アプリケーション/操作に適しているという提案です。

私は、RESTサービス用の小さなクライアントAPIを作成する必要があるアプリケーションに取り組んでいます。4つのRESTエンドポイントを呼び出す必要があります。3つは参照データ(空港、航空会社、ステータス)を取得するためのもので、4つ目は特定の空港の飛行時間を提供するメインサービスです。

3つの参照データサービスを公開するクラスを作成しました。メソッドは次のようになります。

public Observable<IEnumerable<Airport>> GetAirports()
public Observable<IEnumerable<Airline>> GetAirlines()
public Observable<IEnumerable<Status>> GetStatuses()
public Observable<IEnumerable<Flights>> GetFlights(string airport)

GetFlightsメソッドでは、各フライトに、出発する空港とフライトを運用している航空会社の参照を保持する必要があります。そのためには、GetAirportsとGetAirlinesからのデータを利用できるようにする必要があります。各空港、航空会社、ステータスは辞書(つまり辞書)に追加されるので、各フライトを解析するときに参照を簡単に設定できます。

flight.Airport = _airports[flightNode.Attribute("airport").Value]
flight.Airline = _airlines[flightNode.Attribute("airline").Value]
flight.Status = _statuses[flightNode.Attribute("status").Value]

私の現在の実装は次のようになります。

public IObservable<IEnumerable<Flight>> GetFlightsFrom(Airport fromAirport)
{
    var airports = new AirportNamesService().GetAirports();
    var airlines = new AirlineNamesService().GetAirlines();
    var statuses = new StatusService().GetStautses();


    var referenceData = airports
        .ForkJoin(airlines, (allAirports, allAirlines) =>
                            {
                                Airports.AddRange(allAirports);
                                Airlines.AddRange(allAirlines);
                                return new Unit();
                            })
        .ForkJoin(statuses, (nothing, allStatuses) =>
                            {
                                Statuses.AddRange(allStatuses);
                                return new Unit();
                            });

    string url = string.Format(_serviceUrl, 1, 7, fromAirport.Code);

    var flights = from data in referenceData
                    from flight in GetFlightsFrom(url)
                    select flight;

    return flights;
}

private IObservable<IEnumerable<Flight>> GetFlightsFrom(string url)
{
    return WebRequestFactory.GetData(new Uri(url), ParseFlightsXml);
}

現在の実装はSergeyの回答に基づいており、ForkJoinを使用してシーケンシャル実行を保証し、Flightsの前に参照データがロードされるようにします。この実装は、以前の実装のように「ReferenceDataLoaded」イベントを発生させるよりもはるかに洗練されています。

4

2 に答える 2

2

各REST呼び出しからエンティティのリストを受信して​​いる場合、呼び出しには少し異なるシグネチャが必要だと思います。リターンコレクションの各値を監視しているのではなく、呼び出し完了のイベントを監視しているのです。したがって、空港の場合は、次の署名が必要です。

public IObservable<Aiports> GetAirports()

次のステップは、最初の3つを並行して実行し、それらすべてを待つことです。

var ports_lines_statuses = 
    Observable.ForkJoin(GetAirports(), GetAirlines(), GetStatuses());

3番目のステップは、GetFlights()を使用して上記のabservableを作成することです。

var decoratedFlights = 
  from pls in ports_lines_statuses
  let airport = MyAirportFunc(pls)
  from flight in GetFlights(airport)
  select flight;

編集:私はまだあなたのサービスが戻る理由を理解していません

IObservable<Airport> 

それ以外の

IObservable<IEnumerable<Airport>>

AFAIK、REST呼び出しから、すべてのエンティティを一度に取得しますが、ページングを行う可能性がありますか?とにかく、RXにバッファリングを実行させたい場合は、.BufferWithCount()を使用できます。

    var allAirports = new AirportNamesService()
        .GetAirports().BufferWithCount(int.MaxValue); 
...

次に、ForkJoinを適用できます。

var ports_lines_statuses =  
    allAirports
        .ForkJoin(allAirlines, PortsLinesSelector)
        .ForkJoin(statuses, ...

Ports_lines_statusesには、すべての参照データを含むタイムライン上の単一のイベントが含まれます。

編集:これは、新しく作成されたListObservableを使用した別の1つです(最新リリースのみ):

allAiports = airports.Start(); 
allAirlines = airlines.Start();
allStatuses = statuses.Start();

...
whenReferenceDataLoaded =
  Observable.Join(airports.WhenCompleted()
                 .And(airlines.WhenCompleted())
                 .And(statuses.WhenCompleted())
                 Then((p, l, s) => new Unit())); 



    public static IObservable<Unit> WhenCompleted<T>(this IObservable<T> source)
    {
        return source
            .Materialize()
            .Where(n => n.Kind == NotificationKind.OnCompleted)
            .Select(_ => new Unit());
    }
于 2010-05-14T18:03:38.383 に答える
0

ここでのユースケースはプルベースです-IEnumerableは問題ありません。言いたい場合は、新しいフライトが到着する場所を通知してから、プルベースのREST呼び出しをObservable.Generate内でラップすることには価値があるかもしれません。

于 2010-05-15T16:38:47.250 に答える