Exemplo n.º 1
0
        /// <summary>
        /// Creates an observable with two pairwise notification channels by combining the latest values of the specified
        /// observable sequences and choosing which channels will receive values based on the specified function.
        /// </summary>
        /// <typeparam name="TLeft">Type of the left notification channel.</typeparam>
        /// <typeparam name="TRight">Type of the right notification channel.</typeparam>
        /// <param name="leftSource">The observable sequence that provides notifications for the left channel.</param>
        /// <param name="rightSource">The observable sequence that provides notifications for the right channel.</param>
        /// <param name="directionSelector">Selects the channels that will receive notifications for every pair.</param>
        /// <returns>A new observable sequence containing the latest values in the specified observable sequences.</returns>
        public static IObservable <Either <TLeft, TRight> > Pair <TLeft, TRight>(
            this IObservable <TLeft> leftSource,
            IObservable <TRight> rightSource,
            Func <TLeft, TRight, PairDirection> directionSelector)
        {
            Contract.Requires(leftSource != null);
            Contract.Requires(rightSource != null);
            Contract.Requires(directionSelector != null);
            Contract.Ensures(Contract.Result <IObservable <Either <TLeft, TRight> > >() != null);

            return(EitherObservable.Create <TLeft, TRight>(
                       observer =>
                       leftSource.Always().StartWith(Maybe.Empty <TLeft>())
                       .CombineLatest(
                           rightSource.Always().StartWith(Maybe.Empty <TRight>()),
                           (left, right) => new
            {
                left,
                right
            })
                       .SubscribeSafe(
                           pair =>
            {
                if (!pair.left.HasValue)
                {
                    if (pair.right.HasValue)
                    {
                        observer.OnNextRight(pair.right.Value);
                    }
                }
                else if (!pair.right.HasValue)
                {
                    observer.OnNextLeft(pair.left.Value);
                }
                else
                {
                    var left = pair.left.Value;
                    var right = pair.right.Value;

                    switch (directionSelector(left, right))
                    {
                    case PairDirection.Left:
                        observer.OnNextLeft(left);
                        break;

                    case PairDirection.Right:
                        observer.OnNextRight(right);
                        break;

                    case PairDirection.Both:
                        observer.OnNextLeft(left);
                        observer.OnNextRight(right);
                        break;

                    case PairDirection.Neither:
                        break;

                    default:
                        throw new InvalidOperationException(Errors.InvalidPairDirectionValue);
                    }
                }
            },
                           observer.OnError,
                           observer.OnCompleted)));
        }