Самый простой способ сделать это - сначала преобразовать ваши интерфейсы в 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 несколько раз)