diff --git a/Implab/Components/StateChangeEventArgs.cs b/Implab/Components/StateChangeEventArgs.cs
--- a/Implab/Components/StateChangeEventArgs.cs
+++ b/Implab/Components/StateChangeEventArgs.cs
@@ -2,7 +2,7 @@
namespace Implab.Components
{
- public class StateChangeEventArgs {
+ public class StateChangeEventArgs : EventArgs {
///
/// The error information if any
///
diff --git a/Implab/PromiseExtensions.cs b/Implab/PromiseExtensions.cs
--- a/Implab/PromiseExtensions.cs
+++ b/Implab/PromiseExtensions.cs
@@ -47,7 +47,7 @@ namespace Implab {
/// Cleanup.
/// The 1st type parameter.
/// The 2nd type parameter.
- public static TPromise EnsureDispatched(this TPromise that, IPromise head, Action cleanup) where TPromise : IPromise{
+ public static TPromise EnsureDispatched(this TPromise that, IPromise head, Action cleanup) where TPromise : IPromise {
Safe.ArgumentNotNull(that, "that");
Safe.ArgumentNotNull(head, "head");
@@ -56,12 +56,37 @@ namespace Implab {
return that;
}
- public static AsyncCallback AsyncCallback(this Promise that, Func callback) {
+ ///
+ /// Adds a cancellation point to the chain of promises. When a cancellation request reaches the cancellation point the operation is
+ /// cancelled immediatelly, and the request is passed towards. If the operation at the higher level can not be cancelled is't result
+ /// will be collected with callback.
+ ///
+ /// The type of the promise result.
+ /// The promise to which the cancellation point should be attached.
+ /// The callback which is used to cleanup the result of the operation if the cancellation point is cancelled already.
+ /// The promise
+ public static IPromise CancellationPoint(this IPromise that, Action cleanup) {
+ var meduim = new Promise();
+
+ that.On(meduim.Resolve, meduim.Reject, meduim.CancelOperation);
+
+ meduim.CancellationRequested(that.Cancel);
+ meduim.CancellationRequested(meduim.CancelOperation);
+
+ if (cleanup != null)
+ meduim.On((Action)null, null, (e) => {
+ that.On(cleanup);
+ });
+
+ return meduim;
+ }
+
+ public static AsyncCallback AsyncCallback(this Promise that, Func callback) {
Safe.ArgumentNotNull(that, "that");
Safe.ArgumentNotNull(callback, "callback");
var op = TraceContext.Instance.CurrentOperation;
return ar => {
- TraceContext.Instance.EnterLogicalOperation(op,false);
+ TraceContext.Instance.EnterLogicalOperation(op, false);
try {
that.Resolve(callback(ar));
} catch (Exception err) {
@@ -74,9 +99,9 @@ namespace Implab {
static void CancelByTimeoutCallback(object cookie) {
((ICancellable)cookie).Cancel(new TimeoutException());
- }
-
-///
+ }
+
+ ///
/// Cancells promise after the specified timeout is elapsed.
///
/// The promise to cancel on timeout.
@@ -112,7 +137,7 @@ namespace Implab {
}
medium.On(() => {
- foreach(var p2 in that)
+ foreach (var p2 in that)
p2.Cancel();
}, PromiseEventType.ErrorOrCancel);
@@ -148,7 +173,7 @@ namespace Implab {
var results = new T[that.Count];
medium.On(() => {
- foreach(var p2 in that)
+ foreach (var p2 in that)
p2.Cancel();
}, PromiseEventType.ErrorOrCancel);
@@ -216,12 +241,36 @@ namespace Implab {
public static IPromise Then(this IPromise that, Func success, Func error, Func cancel) {
Safe.ArgumentNotNull(that, "that");
- var d = new FuncTask(success, error, cancel, false);
+ var d = new FuncTask(success, error, cancel, false);
that.On(d.Resolve, d.Reject, d.CancelOperation);
d.CancellationRequested(that.Cancel);
return d;
}
+ public static IPromise Then(this IPromise that, Action success, Func error, Func cancel) {
+ Safe.ArgumentNotNull(that, "that");
+ var d = new FuncTask(
+ x => {
+ success(x);
+ return x;
+ },
+ error,
+ cancel,
+ false
+ );
+ that.On(d.Resolve, d.Reject, d.CancelOperation);
+ d.CancellationRequested(that.Cancel);
+ return d;
+ }
+
+ public static IPromise Then(this IPromise that, Action success, Func error) {
+ return Then(that, success, error, null);
+ }
+
+ public static IPromise Then(this IPromise that, Action success) {
+ return Then(that, success, null, null);
+ }
+
public static IPromise Then(this IPromise that, Func success, Func error) {
return Then(that, success, error, null);
}
@@ -230,8 +279,79 @@ namespace Implab {
return Then(that, success, null, null);
}
+ public static IPromise Always(this IPromise that, Action handler) {
+ Func errorOrCancel;
+ if (handler != null)
+ errorOrCancel = e => {
+ handler();
+ throw new PromiseTransientException(e);
+ };
+ else
+ errorOrCancel = null;
+
+ return Then(
+ that,
+ x => {
+ handler();
+ return x;
+ },
+ errorOrCancel,
+ errorOrCancel);
+ }
+
+ public static IPromise Always(this IPromise that, Action handler) {
+ Action errorOrCancel;
+ if (handler != null)
+ errorOrCancel = e => {
+ handler();
+ throw new PromiseTransientException(e);
+ };
+ else
+ errorOrCancel = null;
+
+ return Then(
+ that,
+ handler,
+ errorOrCancel,
+ errorOrCancel);
+ }
+
+ public static IPromise Error(this IPromise that, Action handler, bool handleCancellation) {
+ Action errorOrCancel;
+ if (handler != null)
+ errorOrCancel = e => {
+ handler(e);
+ throw new PromiseTransientException(e);
+ };
+ else
+ errorOrCancel = null;
+
+ return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
+ }
+
+ public static IPromise Error(this IPromise that, Action handler) {
+ return Error(that, handler, false);
+ }
+
+ public static IPromise Error(this IPromise that, Action handler, bool handleCancellation) {
+ Func errorOrCancel;
+ if (handler != null)
+ errorOrCancel = e => {
+ handler(e);
+ throw new PromiseTransientException(e);
+ };
+ else
+ errorOrCancel = null;
+
+ return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
+ }
+
+ public static IPromise Error(this IPromise that, Action handler) {
+ return Error(that, handler, false);
+ }
+
#region chain traits
- public static IPromise Chain(this IPromise that, Func success, Func error, Func cancel) {
+ public static IPromise Chain(this IPromise that, Func success, Func error, Func cancel) {
Safe.ArgumentNotNull(that, "that");
var d = new ActionChainTask(success, error, cancel, false);
@@ -240,7 +360,7 @@ namespace Implab {
return d;
}
- public static IPromise Chain(this IPromise that, Func success, Func error) {
+ public static IPromise Chain(this IPromise that, Func success, Func error) {
return Chain(that, success, error, null);
}
@@ -268,7 +388,7 @@ namespace Implab {
public static IPromise Chain(this IPromise that, Func> success, Func> error, Func> cancel) {
Safe.ArgumentNotNull(that, "that");
- var d = new FuncChainTask(success, error, cancel, false);
+ var d = new FuncChainTask(success, error, cancel, false);
that.On(d.Resolve, d.Reject, d.CancelOperation);
if (success != null)
d.CancellationRequested(that.Cancel);
@@ -281,20 +401,20 @@ namespace Implab {
public static IPromise Chain(this IPromise that, Func> success) {
return Chain(that, success, null, null);
- }
-
+ }
+
#endregion
-
-
- #if NET_4_5
-
+
+
+#if NET_4_5
+
public static PromiseAwaiter GetAwaiter(this IPromise that) {
Safe.ArgumentNotNull(that, "that");
return new PromiseAwaiter(that);
- }
-
- #endif
+ }
+
+#endif
}
}
diff --git a/Implab/Safe.cs b/Implab/Safe.cs
--- a/Implab/Safe.cs
+++ b/Implab/Safe.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
+using System.Collections;
namespace Implab
{
@@ -60,12 +61,28 @@ namespace Implab
}
}
+ public static void Dispose(IEnumerable objects) {
+ foreach (var d in objects)
+ if (d != null)
+ d.Dispose();
+ }
+
public static void Dispose(object obj) {
var d = obj as IDisposable;
if (d != null)
d.Dispose();
}
+ public static void DispatchEvent(this EventHandler handler, object sender, T args) {
+ if (handler != null)
+ handler(sender, args);
+ }
+
+ public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) {
+ if (handler != null)
+ handler(sender, args);
+ }
+
[DebuggerStepThrough]
public static IPromise Run(Func action) {
ArgumentNotNull(action, "action");