diff Implab/Promise.cs @ 96:daffa72a1cec v2

Added the chaining method to the non-generic IPromise
author cin
date Thu, 30 Oct 2014 10:06:16 +0300
parents 4f20870d0816
children 8ddf1648eca4
line wrap: on
line diff
--- a/Implab/Promise.cs	Wed Oct 29 18:54:46 2014 +0300
+++ b/Implab/Promise.cs	Thu Oct 30 10:06:16 2014 +0300
@@ -351,6 +351,7 @@
         /// <param name="error">Обработчик ошибки. Данный обработчик получит
         /// исключение возникшее при выполнении операции.</param>
         /// <returns>Новое обещание, которое будет выполнено при выполнении исходного обещания.</returns>
+        /// <param name = "cancel"></param>
         public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error, Action cancel) {
             Safe.ArgumentNotNull(mapper, "mapper");
             
@@ -413,6 +414,7 @@
         /// <param name="error">Обработчик ошибки. Данный обработчик получит
         /// исключение возникшее при выполнении текуещй операции.</param>
         /// <returns>Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции.</returns>
+        /// <param name = "cancel"></param>
         public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error, Action cancel) {
 
             Safe.ArgumentNotNull(chained, "chained");
@@ -759,29 +761,119 @@
 
         IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) {
             return Then(
-                x => success(),
-                e => {
+                success != null ? new ResultHandler<T>(x => success()) : null,
+                error != null ? new ErrorHandler<T>(e => {
                     error(e);
                     return default(T);
-                },
+                }) : null,
                 cancel
             );
         }
 
         IPromise IPromise.Then(Action success, ErrorHandler error) {
             return Then(
-                x => success(),
-                e => {
+                success != null ? new ResultHandler<T>(x => success()) : null,
+                error != null ? new ErrorHandler<T>(e => {
                     error(e);
                     return default(T);
-                }
+                }) : null
             );
         }
 
         IPromise IPromise.Then(Action success) {
+            Safe.ArgumentNotNull(success, "success");
             return Then(x => success());
         }
 
+        IPromise IPromise.Chain(Func<IPromise> chained, ErrorHandler<IPromise> error, Action cancel) {
+            return ChainNoResult(chained, error, cancel);
+        }
+
+        IPromise ChainNoResult(Func<IPromise> chained, ErrorHandler<IPromise> error, Action cancel) {
+                Safe.ArgumentNotNull(chained, "chained");
+
+            var medium = new Promise<object>(this, true);
+
+                ResultHandler<T> resultHandler = delegate(T result) {
+                    if (medium.IsCancelled)
+                        return;
+
+                    var promise = chained();
+
+                    promise.Last(
+                        medium.Resolve,
+                        medium.Reject,
+                        () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка
+                    );
+
+                    // notify chained operation that it's not needed anymore
+                    // порядок вызова Then, Cancelled важен, поскольку от этого
+                    // зависит IsExclusive
+                    medium.Cancelled(() => {
+                        if (promise.IsExclusive)
+                            promise.Cancel();
+                    });
+                };
+
+                ErrorHandler<T> errorHandler;
+
+                if (error != null)
+                    errorHandler = delegate(Exception e) {
+                    try {
+                        var promise = error(e);
+
+                        promise.Last(
+                            medium.Resolve,
+                            medium.Reject,
+                            () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка
+                        );
+
+                        // notify chained operation that it's not needed anymore
+                        // порядок вызова Then, Cancelled важен, поскольку от этого
+                        // зависит IsExclusive
+                        medium.Cancelled(() => {
+                            if (promise.IsExclusive)
+                                promise.Cancel();
+                        });
+                    } catch (Exception e2) {
+                        medium.Reject(e2);
+                    }
+                    return default(T);
+                };
+                else
+                    errorHandler = err => {
+                    medium.Reject(err);
+                    return default(T);
+                };
+
+
+                Action cancelHandler;
+                if (cancel != null)
+                    cancelHandler = () => {
+                    if (cancel != null)
+                        cancel();
+                    medium.Cancel();
+                };
+                else
+                    cancelHandler = medium.Cancel;
+
+                AddHandler(
+                    resultHandler,
+                    errorHandler,
+                    cancelHandler,
+                    null
+                );
+
+                return medium;
+        }
+        IPromise IPromise.Chain(Func<IPromise> chained, ErrorHandler<IPromise> error) {
+            return ChainNoResult(chained, error, null);
+        }
+        IPromise IPromise.Chain(Func<IPromise> chained) {
+            return ChainNoResult(chained, null, null);
+        }            
+
+
         void IPromise.Last(Action success, ErrorHandler error, Action cancel) {
             Last(x => success(), error, cancel);
         }