Пример #1
0
        public static Await <R> Condition <TEventArgs, TEventHandler, R>(
            Func <Optional <TEventArgs>, Optional <R> > choose,
            Action <TEventHandler> subscribe,
            Action <TEventHandler> unsubscribe,
            Func <Action <object, TEventArgs>, TEventHandler> convert)
        {
            return(complete =>
            {
                // Create helper action to safely invoke choose action and supply result to completed.
                Func <Optional <TEventArgs>, Complete <R>, bool> tryChooseAndComplete = (e, doComplete) =>
                {
                    var choice = Try.Do(() => choose(e));
                    if (choice.IsSuccess && choice.Success.IsNone)
                    {
                        return false;
                    }

                    doComplete(choice.Map(x => x.Some));
                    return true;
                };

                // When some result is chosen or exception thrown in process,
                // Then handle it and return immediately - Nothing to Cancel here.
                if (tryChooseAndComplete(None.Of <TEventArgs>(), complete))
                {
                    return NothingToCancel;
                }

                var eventHandler = default(TEventHandler);
                var completeFirst = new CompleteFirst();
                Complete <R> completeAndUnsubscribe = x => completeFirst.Do(() =>
                {
                    var unsubscription = Try.Do(() => unsubscribe(eventHandler));

                    // Replacing original failure with unsubscription failure if got one.
                    complete(unsubscription.IsError ? Error.Of <R>(unsubscription.Error) : x);
                });

                // Convert action to event handler delegate (ignoring event source) and subscribe it.
                var subscription = Try.Do(() => subscribe(
                                              eventHandler = convert((_, e) => tryChooseAndComplete(e, completeAndUnsubscribe))));

                if (subscription.IsError)
                {
                    complete(Error.Of <R>(subscription.Error));
                    return NothingToCancel;
                }

                // In case that during subscribe, condition become true (e.g. event was already raised and will never be raised again)
                // We are checking condition one more time.
                if (tryChooseAndComplete(None.Of <TEventArgs>(), completeAndUnsubscribe))
                {
                    return NothingToCancel;
                }

                // Return Cancel with None result.
                return () => completeAndUnsubscribe(None.Of <Result <R> >());
            });
        }
Пример #2
0
        public static Await <R> Many <T, R>(
            Func <Result <T>, int, Optional <R> > choose,
            R defaultResult,
            params Await <T>[] sources)
        {
            return(complete =>
            {
                var cancels = Stack <Cancelable> .Empty;
                var completeFirst = new CompleteFirst();
                var completeLast = new CompleteLast(sources.Length);

                Complete <R> cancelRestAndComplete = result => completeFirst.Do(() =>
                {
                    cancels.ForEach(x => Try.Do(() => x()));
                    complete(result);
                });

                for (var i = 0; i < sources.Length; i++)
                {
                    var index = i; // save index to use in lambda
                    var current = sources[i](result =>
                    {
                        if (result.IsNone) // it means that we ignoring external canceling.
                        {
                            return;
                        }

                        var choice = Try.Do(() => choose(result.Some, index));
                        if (choice.IsError)
                        {
                            cancelRestAndComplete(Error.Of <R>(choice.Error));
                        }
                        else if (choice.Success.IsSome)
                        {
                            cancelRestAndComplete(Success.Of(choice.Success.Some));
                        }
                        else // at last try to complete whole workflow with default result.
                        {
                            completeLast.Do(() => completeFirst.Do(() => complete(Success.Of(defaultResult))));
                        }
                    });

                    if (completeFirst.IsCompleted) // if all is done just return
                    {
                        return NothingToCancel;
                    }

                    cancels = cancels.Add(current);
                }

                return () => cancelRestAndComplete(None.Of <Result <R> >());
            });
        }
Пример #3
0
        public static Await <R> Many <T1, T2, R>(
            Await <T1> source1,
            Await <T2> source2,
            R defaultResult,
            Func <Optional <Result <T1> >, Optional <Result <T2> >, Optional <R> > choose)
        {
            var result1 = None.Of <Result <T1> >();
            var result2 = None.Of <Result <T2> >();

            return(Many(
                       (_, i) => choose(result1, result2),
                       defaultResult,
                       source1.Take(result => result1 = Success.Of(result)),
                       source2.Take(result => result2 = Success.Of(result))));
        }
Пример #4
0
        public static Await <T> Operation <T>(Func <T> operation, Func <Action, Cancelable> invoker)
        {
            return(complete =>
            {
                var completeFirst = new CompleteFirst();
                var cancel = invoker(() =>
                {
                    var result = Try.Do(operation);
                    completeFirst.Do(() => complete(result));
                });

                return () => completeFirst.Do(() =>
                {
                    Try.Do(() => cancel());
                    complete(None.Of <Result <T> >());
                });
            });
        }
Пример #5
0
 public static Await <R> Map <T, R>(this Await <T> source, Func <T, R> map)
 {
     return(complete => source(result =>
     {
         if (result.IsNone)
         {
             complete(None.Of <Result <R> >());
         }
         else if (result.Some.IsError)
         {
             complete(Error.Of <R>(result.Some.Error));
         }
         else
         {
             var converted = Try.Do(() => map(result.Some.Success));
             complete(converted.IsSuccess ? Success.Of(converted.Success) : Error.Of <R>(converted.Error));
         }
     }));
 }
Пример #6
0
        public static Optional <Result <T> > Wait <T>(this Await <T> source, int timeoutMilliseconds = Timeout.Infinite)
        {
            var completed = new AutoResetEvent(false);

            var result = None.Of <Result <T> >();
            var cancel = source(x =>
            {
                result = x;
                completed.Set();
            });

            if (completed.WaitOne(timeoutMilliseconds))
            {
                return(result);
            }

            cancel();
            return(None.Of <Result <T> >());
        }
Пример #7
0
 public static Optional <T> Of <T>(T value)
 {
     return((object)value == null?None.Of <T>() : Some.Of(value));
 }
Пример #8
0
        public static Await <Result <T>[]> All <T>(params Await <T>[] sources)
        {
            var results = new Result <T> [sources.Length];

            return(Many((x, i) => None.Of <Result <T>[]>().Apply(_ => results[i] = x), results, sources));
        }