示例#1
0
    /// <summary>
    /// Handles an interaction and asynchronously returns the result.
    /// </summary>
    /// <remarks>
    /// <para>
    /// This method passes the interaction in turn to its registered handlers in reverse order of registration
    /// until one of them handles the interaction. If the interaction remains unhandled after all
    /// its registered handlers have executed, an <see cref="UnhandledInteractionException{TInput, TOutput}"/> is thrown.
    /// </para>
    /// </remarks>
    /// <param name="input">
    /// The input for the interaction.
    /// </param>
    /// <returns>
    /// An observable that ticks when the interaction completes.
    /// </returns>
    /// <exception cref="UnhandledInteractionException{TInput, TOutput}">Thrown when no handler handles the interaction.</exception>
    public virtual IObservable <TOutput> Handle(TInput input)
    {
        var context = new InteractionContext <TInput, TOutput>(input);

        return(GetHandlers()
               .Reverse()
               .ToObservable()
               .ObserveOn(_handlerScheduler)
               .Select(handler => Observable.Defer(() => handler(context)))
               .Concat()
               .TakeWhile(_ => !context.IsHandled)
               .IgnoreElements()
               .Select(_ => default(TOutput) !)
               .Concat(
                   Observable.Defer(
                       () => context.IsHandled
                                                  ? Observable.Return(context.GetOutput())
                                                  : Observable.Throw <TOutput>(new UnhandledInteractionException <TInput, TOutput>(this, input)))));
    }