вопрос noob - просмотр результата двух асинхронных методов, которые возвращают Action <T> - PullRequest
0 голосов
/ 08 июля 2011

У меня есть следующие 2 асинхронных метода, которые используют обратные вызовы Action

public interface IGeoCoordinateService
{
    void Start(Action<GeoPosition<GeoCoordinate>> positionCallback, Action<Exception> exceptionCallback);
}

public interface IGooglePlacesService
{
    void FindLocations(GeoCoordinate geoCoordinate, SearchFilter searchFilter, Action<PlaceSearchResponse> searchCallback);
}
  • Я должен убедиться, что у меня есть результат от GeoCoordinateService, прежде чем я хочу выполнить GooglePlacesService.
  • Я также хочу запускать GooglePlacesService каждый раз, когда меняется GeoCoordinate (и не ноль)

Самый простой способ сделать это с Rx? (Я крайне нуб, поэтому, пожалуйста, будьте осторожны с Rx Lingo)

1 Ответ

2 голосов
/ 08 июля 2011

Самый простой способ сделать это - сначала преобразовать ваши интерфейсы в IObservables.Чтобы сделать это, я собираюсь сделать некоторые предположения относительно вашего API:

  • IGeoCoordinateService может вызывать positionCallback несколько раз после запуска.
  • Если IGeoCoordinateService вызывает exceptionCallback, это делается ибольше не будет вызывать positionCallback.(Это предположение необходимо для соответствия контракту IObservable.)
  • IGooglePlacesService вызывает searchCallback только один раз.(Это предположение полезно для SelectMany, который я сделаю позже.)

Оттуда вы можете написать следующие функции:

public IObservable<GeoPosition<GeoCoordinate>> ToObservable(this IGeoCoordinateService service)
{
    return Observable.Create((IObserver<GeoPosition<GeoCoordinate>> observer) =>
                             {
                                 service.Start(observer.OnNext, observer.OnError);
                                 //nothing to do on unsubscribe, cannot cancel run
                                 return (() => {});
                             })
}

public Func<GeoCoordinate, SearchFilter, IObservable<PlaceSearchResponse>>
ToObservable(IGooglePlacesService service)
{
    return (coord, filter) =>
           {
               return Observable.Create((IObserver<PlaceSearchResponse> observer) =>
                                        {
                                            service.FindLocations(coord, filter,
                                                                  (value) =>
                                                                  {
                                                                      observer.OnNext(value);
                                                                      observer.OnCompleted();
                                                                  });
                                            //nothing to do on unsubscribe, cannot cancel run
                                            return (() => {});
                                        })
           }
}

Теперь, когда вы можете преобразовать службы вIObservables, вы можете объединить их в цепочку следующим образом (надеюсь, вы можете придумать лучшее имя функции):

public IObservable<PlaceSearchResponse> ChainServices(IGeoCoordinateService geo, IGooglePlacesService place, SearchFilter filter)
{
    return from pos in geo.ToObservable()
           where pos != null && pos.Coordinate != null
           from placeResponsen place.ToObservable()(pos.Coordinate, filter)
           select placeResponse;
}

Обратите внимание, что, как обычно для IObservables, вызов ChainServices ничего не делает, вы должны вызвать Subscribe для возвращаемогоIObservable для фактического выполнения асинхронных вызовов.

Некоторые вещи, которые API мог бы использовать, если у вас есть какой-либо элемент управления:

  • некоторый способ отменить частичный вызов (IObservable делает этовозвращая IDisposable из подписки)
  • каким-то образом сказать, когда IGeoCoordinateService сделан, чтобы иметь возможность вызывать OnCompleted для наблюдателей (предполагая, что он вызывает positionCallback несколько раз)
...