// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. #if HAS_WINRT using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Reactive.Threading.Tasks; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; using Windows.Foundation; namespace System.Reactive.Linq { /// /// Provides a set of extension methods to expose observable sequences as Windows Runtime asynchronous actions and operations. /// public static class AsyncInfoObservable { #region IAsyncAction /// /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence. /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous action. /// Windows Runtime asynchronous action object representing the completion of the observable sequence. /// is null. public static IAsyncAction ToAsyncAction(this IObservable source) { if (source == null) throw new ArgumentNullException("source"); return AsyncInfo.Run(ct => (Task)source.DefaultIfEmpty().ToTask(ct)); } #region Progress /// /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence, reporting incremental progress for each element produced by the sequence. /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous action. /// Windows Runtime asynchronous action object representing the completion of the observable sequence, reporting incremental progress for each source sequence element. /// is null. public static IAsyncActionWithProgress ToAsyncActionWithProgress(this IObservable source) { if (source == null) throw new ArgumentNullException("source"); return AsyncInfo.Run((ct, progress) => { var i = 0; return (Task)source.Do(_ => progress.Report(i++)).DefaultIfEmpty().ToTask(ct); }); } /// /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence, using a selector function to map the source sequence on a progress reporting sequence. /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed. /// /// The type of the elements in the source sequence. /// The type of the elements in the progress sequence. /// Source sequence to expose as an asynchronous action and to compute a progress sequence that gets reported through the asynchronous action. /// Selector function to map the source sequence on a progress reporting sequence. /// Windows Runtime asynchronous action object representing the completion of the result sequence, reporting progress computed through the progress sequence. /// or is null. public static IAsyncActionWithProgress ToAsyncActionWithProgress(this IObservable source, Func, IObservable> progressSelector) { if (source == null) throw new ArgumentNullException("source"); if (progressSelector == null) throw new ArgumentNullException("progressSelector"); return AsyncInfo.Run((ct, progress) => { return (Task)Observable.Create(observer => { var obs = Observer.Synchronize(observer); var data = source.Publish(); var progressSubscription = progressSelector(data).Subscribe(progress.Report, obs.OnError); var dataSubscription = data.DefaultIfEmpty().Subscribe(obs); var connection = data.Connect(); return new CompositeDisposable(progressSubscription, dataSubscription, connection); }).ToTask(ct); }); } #endregion #endregion #region IAsyncOperation /// /// Creates a Windows Runtime asynchronous operation that returns the last element of the observable sequence. /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous operation. /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence. /// is null. public static IAsyncOperation ToAsyncOperation(this IObservable source) { if (source == null) throw new ArgumentNullException("source"); return AsyncInfo.Run(ct => source.ToTask(ct)); } /// /// Creates a Windows Runtime asynchronous operation that returns the last element of the observable sequence, reporting incremental progress for each element produced by the sequence. /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. /// /// The type of the elements in the source sequence. /// Source sequence to expose as an asynchronous operation. /// Windows Runtime asynchronous operation object that returns the last element of the observable sequence, reporting incremental progress for each source sequence element. /// is null. public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source) { if (source == null) throw new ArgumentNullException("source"); return AsyncInfo.Run((ct, progress) => { var i = 0; return source.Do(_ => progress.Report(i++)).ToTask(ct); }); } #region Progress /// /// Creates a Windows Runtime asynchronous operation that returns the last element of the result sequence, reporting incremental progress for each element produced by the source sequence. /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. /// /// The type of the elements in the source sequence. /// The type of the elements in the result sequence. /// Source sequence to compute a result sequence that gets exposed as an asynchronous operation. /// Selector function to map the source sequence on a result sequence. /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting incremental progress for each source sequence element. /// or is null. public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector) { if (source == null) throw new ArgumentNullException("source"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); return AsyncInfo.Run((ct, progress) => { var i = 0; return resultSelector(source.Do(_ => progress.Report(i++))).ToTask(ct); }); } /// /// Creates a Windows Runtime asynchronous operation that returns the last element of the result sequence, using a selector function to map the source sequence on a progress reporting sequence. /// Upon cancellation of the asynchronous operation, the subscription to the source sequence will be disposed. /// /// The type of the elements in the source sequence. /// The type of the elements in the result sequence. /// The type of the elements in the progress sequence. /// Source sequence to compute a result sequence that gets exposed as an asynchronous operation and a progress sequence that gets reported through the asynchronous operation. /// Selector function to map the source sequence on a result sequence. /// Selector function to map the source sequence on a progress reporting sequence. /// Windows Runtime asynchronous operation object that returns the last element of the result sequence, reporting progress computed through the progress sequence. /// or or is null. public static IAsyncOperationWithProgress ToAsyncOperationWithProgress(this IObservable source, Func, IObservable> resultSelector, Func, IObservable> progressSelector) { if (source == null) throw new ArgumentNullException("source"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); if (progressSelector == null) throw new ArgumentNullException("progressSelector"); return AsyncInfo.Run((ct, progress) => { return Observable.Create(observer => { var obs = Observer.Synchronize(observer); var data = source.Publish(); var progressSubscription = progressSelector(data).Subscribe(progress.Report, obs.OnError); var dataSubscription = resultSelector(data).Subscribe(obs); var connection = data.Connect(); return new CompositeDisposable(progressSubscription, dataSubscription, connection); }).ToTask(ct); }); } #endregion #endregion } } #endif