Policy<TResult>
public abstract class Policy<TResult> : PolicyBase, IAsyncPolicy<TResult>, IsPolicy, ISyncPolicy<TResult>
Transient fault handling policies that can be applied to delegates returning results of type TResult
using Polly.Utilities;
using Polly.Wrap;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Polly
{
public abstract class Policy<TResult> : PolicyBase, IAsyncPolicy<TResult>, IsPolicy, ISyncPolicy<TResult>
{
private readonly Func<Func<Context, CancellationToken, Task<TResult>>, Context, CancellationToken, bool, Task<TResult>> _asyncExecutionPolicy;
private readonly Func<Func<Context, CancellationToken, TResult>, Context, CancellationToken, TResult> _executionPolicy;
internal IEnumerable<ResultPredicate<TResult>> ResultPredicates { get; }
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<Task<TResult>> action)
{
return ExecuteAsync((Context ctx, CancellationToken ct) => action(), new Context(), CancellationToken.None, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<Context, Task<TResult>> action, IDictionary<string, object> contextData)
{
return ExecuteAsync((Context ctx, CancellationToken ct) => action(ctx), new Context(contextData), CancellationToken.None, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<Context, Task<TResult>> action, Context context)
{
return ExecuteAsync((Context ctx, CancellationToken ct) => action(ctx), context, CancellationToken.None, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<CancellationToken, Task<TResult>> action, CancellationToken cancellationToken)
{
return ExecuteAsync((Context ctx, CancellationToken ct) => action(ct), new Context(), cancellationToken, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<CancellationToken, Task<TResult>> action, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
return ExecuteAsync((Context ctx, CancellationToken ct) => action(ct), new Context(), cancellationToken, continueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<Context, CancellationToken, Task<TResult>> action, IDictionary<string, object> contextData, CancellationToken cancellationToken)
{
return ExecuteAsync(action, new Context(contextData), cancellationToken, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken)
{
return ExecuteAsync(action, context, cancellationToken, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<Context, CancellationToken, Task<TResult>> action, IDictionary<string, object> contextData, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
return ExecuteAsync(action, new Context(contextData), cancellationToken, continueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<TResult> ExecuteAsync(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
if (context == null)
throw new ArgumentNullException("context");
SetPolicyContext(context);
return ExecuteAsyncInternal(action, context, cancellationToken, continueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<Task<TResult>> action)
{
return ExecuteAndCaptureAsync((Context ctx, CancellationToken ct) => action(), new Context(), CancellationToken.None, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<Context, Task<TResult>> action, IDictionary<string, object> contextData)
{
return ExecuteAndCaptureAsync((Context ctx, CancellationToken ct) => action(ctx), new Context(contextData), CancellationToken.None, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<Context, Task<TResult>> action, Context context)
{
return ExecuteAndCaptureAsync((Context ctx, CancellationToken ct) => action(ctx), context, CancellationToken.None, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<CancellationToken, Task<TResult>> action, CancellationToken cancellationToken)
{
return ExecuteAndCaptureAsync((Context ctx, CancellationToken ct) => action(ct), new Context(), cancellationToken, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<CancellationToken, Task<TResult>> action, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
return ExecuteAndCaptureAsync((Context ctx, CancellationToken ct) => action(ct), new Context(), cancellationToken, continueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<Context, CancellationToken, Task<TResult>> action, IDictionary<string, object> contextData, CancellationToken cancellationToken)
{
return ExecuteAndCaptureAsync(action, new Context(contextData), cancellationToken, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken)
{
return ExecuteAndCaptureAsync(action, context, cancellationToken, PolicyBase.DefaultContinueOnCapturedContext);
}
[DebuggerStepThrough]
public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<Context, CancellationToken, Task<TResult>> action, IDictionary<string, object> contextData, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
return ExecuteAndCaptureAsync(action, new Context(contextData), cancellationToken, continueOnCapturedContext);
}
public async Task<PolicyResult<TResult>> ExecuteAndCaptureAsync(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
if (this._asyncExecutionPolicy == null)
throw new InvalidOperationException("Please use asynchronous-defined policies when calling asynchronous ExecuteAsync (and similar) methods.");
if (context != null)
try {
TResult result = await this.ExecuteAsync(action, context, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext);
if (Enumerable.Any<ResultPredicate<TResult>>(this.ResultPredicates, (Func<ResultPredicate<TResult>, bool>)((ResultPredicate<TResult> predicate) => predicate(result))))
return PolicyResult<TResult>.Failure(result, context);
return PolicyResult<TResult>.Successful(result, context);
} catch (Exception exception) {
return PolicyResult<TResult>.Failure(exception, Policy<TResult>.GetExceptionType(base.ExceptionPredicates, exception), context);
}
throw new ArgumentNullException("context");
}
public static PolicyBuilder<TResult> Handle<TException>() where TException : Exception
{
return new PolicyBuilder<TResult>((ExceptionPredicate)delegate(Exception exception) {
if (!(exception is TException))
return null;
return exception;
});
}
public static PolicyBuilder<TResult> Handle<TException>(Func<TException, bool> exceptionPredicate) where TException : Exception
{
return new PolicyBuilder<TResult>((ExceptionPredicate)delegate(Exception exception) {
TException arg;
if ((arg = (exception as TException)) == null || !exceptionPredicate(arg))
return null;
return exception;
});
}
public static PolicyBuilder<TResult> HandleInner<TException>() where TException : Exception
{
return new PolicyBuilder<TResult>(PolicyBuilder.HandleInner((Exception ex) => ex is TException));
}
public static PolicyBuilder<TResult> HandleInner<TException>(Func<TException, bool> exceptionPredicate) where TException : Exception
{
return new PolicyBuilder<TResult>(PolicyBuilder.HandleInner(delegate(Exception ex) {
TException arg;
if ((arg = (ex as TException)) != null)
return exceptionPredicate(arg);
return false;
}));
}
public static PolicyBuilder<TResult> HandleResult(Func<TResult, bool> resultPredicate)
{
return new PolicyBuilder<TResult>(resultPredicate);
}
public static PolicyBuilder<TResult> HandleResult(TResult result)
{
return HandleResult(delegate(TResult r) {
if (r == null || !r.Equals(result)) {
if (r == null)
return result == null;
return false;
}
return true;
});
}
public Policy<TResult> WithPolicyKey(string policyKey)
{
if (policyKeyInternal != null)
throw PolicyBase.PolicyKeyMustBeImmutableException;
policyKeyInternal = policyKey;
return this;
}
ISyncPolicy<TResult> ISyncPolicy<TResult>.WithPolicyKey(string policyKey)
{
if (policyKeyInternal != null)
throw PolicyBase.PolicyKeyMustBeImmutableException;
policyKeyInternal = policyKey;
return this;
}
IAsyncPolicy<TResult> IAsyncPolicy<TResult>.WithPolicyKey(string policyKey)
{
if (policyKeyInternal != null)
throw PolicyBase.PolicyKeyMustBeImmutableException;
policyKeyInternal = policyKey;
return this;
}
protected Policy(Func<Func<Context, CancellationToken, Task<TResult>>, Context, CancellationToken, bool, Task<TResult>> asyncExecutionPolicy, IEnumerable<ExceptionPredicate> exceptionPredicates, IEnumerable<ResultPredicate<TResult>> resultPredicates)
{
if (asyncExecutionPolicy == null)
throw new ArgumentNullException("asyncExecutionPolicy");
_asyncExecutionPolicy = asyncExecutionPolicy;
base.ExceptionPredicates = (exceptionPredicates ?? PredicateHelper.EmptyExceptionPredicates);
ResultPredicates = (resultPredicates ?? PredicateHelper<TResult>.EmptyResultPredicates);
}
[DebuggerStepThrough]
internal Task<TResult> ExecuteAsyncInternal(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
if (_asyncExecutionPolicy == null)
throw new InvalidOperationException("Please use asynchronous-defined policies when calling asynchronous ExecuteAsync (and similar) methods.");
return _asyncExecutionPolicy(action, context, cancellationToken, continueOnCapturedContext);
}
[DebuggerStepThrough]
public TResult Execute(Func<TResult> action)
{
return Execute((Context ctx, CancellationToken ct) => action(), new Context(), PolicyBase.DefaultCancellationToken);
}
[DebuggerStepThrough]
public TResult Execute(Func<Context, TResult> action, IDictionary<string, object> contextData)
{
return Execute((Context ctx, CancellationToken ct) => action(ctx), new Context(contextData), PolicyBase.DefaultCancellationToken);
}
[DebuggerStepThrough]
public TResult Execute(Func<Context, TResult> action, Context context)
{
return Execute((Context ctx, CancellationToken ct) => action(ctx), context, PolicyBase.DefaultCancellationToken);
}
[DebuggerStepThrough]
public TResult Execute(Func<CancellationToken, TResult> action, CancellationToken cancellationToken)
{
return Execute((Context ctx, CancellationToken ct) => action(ct), new Context(), cancellationToken);
}
[DebuggerStepThrough]
public TResult Execute(Func<Context, CancellationToken, TResult> action, IDictionary<string, object> contextData, CancellationToken cancellationToken)
{
return Execute(action, new Context(contextData), cancellationToken);
}
[DebuggerStepThrough]
public TResult Execute(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken)
{
if (context == null)
throw new ArgumentNullException("context");
SetPolicyContext(context);
return ExecuteInternal(action, context, cancellationToken);
}
[DebuggerStepThrough]
public PolicyResult<TResult> ExecuteAndCapture(Func<TResult> action)
{
return ExecuteAndCapture((Context ctx, CancellationToken ct) => action(), new Context(), PolicyBase.DefaultCancellationToken);
}
[DebuggerStepThrough]
public PolicyResult<TResult> ExecuteAndCapture(Func<Context, TResult> action, IDictionary<string, object> contextData)
{
return ExecuteAndCapture((Context ctx, CancellationToken ct) => action(ctx), new Context(contextData), PolicyBase.DefaultCancellationToken);
}
[DebuggerStepThrough]
public PolicyResult<TResult> ExecuteAndCapture(Func<Context, TResult> action, Context context)
{
return ExecuteAndCapture((Context ctx, CancellationToken ct) => action(ctx), context, PolicyBase.DefaultCancellationToken);
}
[DebuggerStepThrough]
public PolicyResult<TResult> ExecuteAndCapture(Func<CancellationToken, TResult> action, CancellationToken cancellationToken)
{
return ExecuteAndCapture((Context ctx, CancellationToken ct) => action(ct), new Context(), cancellationToken);
}
[DebuggerStepThrough]
public PolicyResult<TResult> ExecuteAndCapture(Func<Context, CancellationToken, TResult> action, IDictionary<string, object> contextData, CancellationToken cancellationToken)
{
return ExecuteAndCapture(action, new Context(contextData), cancellationToken);
}
[DebuggerStepThrough]
public PolicyResult<TResult> ExecuteAndCapture(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken)
{
if (_executionPolicy == null)
throw new InvalidOperationException("Please use the synchronous-defined policies when calling the synchronous Execute (and similar) methods.");
if (context != null)
try {
TResult result = Execute(action, context, cancellationToken);
if (!Enumerable.Any<ResultPredicate<TResult>>(ResultPredicates, (Func<ResultPredicate<TResult>, bool>)((ResultPredicate<TResult> predicate) => predicate(result))))
return PolicyResult<TResult>.Successful(result, context);
return PolicyResult<TResult>.Failure(result, context);
} catch (Exception exception) {
return PolicyResult<TResult>.Failure(exception, GetExceptionType(base.ExceptionPredicates, exception), context);
}
throw new ArgumentNullException("context");
}
internal static ExceptionType GetExceptionType(IEnumerable<ExceptionPredicate> exceptionPredicates, Exception exception)
{
return Policy.GetExceptionType(exceptionPredicates, exception);
}
protected Policy(Func<Func<Context, CancellationToken, TResult>, Context, CancellationToken, TResult> executionPolicy, IEnumerable<ExceptionPredicate> exceptionPredicates, IEnumerable<ResultPredicate<TResult>> resultPredicates)
{
if (executionPolicy == null)
throw new ArgumentNullException("executionPolicy");
_executionPolicy = executionPolicy;
base.ExceptionPredicates = (exceptionPredicates ?? PredicateHelper.EmptyExceptionPredicates);
ResultPredicates = (resultPredicates ?? PredicateHelper<TResult>.EmptyResultPredicates);
}
[DebuggerStepThrough]
internal TResult ExecuteInternal(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken)
{
if (_executionPolicy == null)
throw new InvalidOperationException("Please use the synchronous-defined policies when calling the synchronous Execute (and similar) methods.");
return _executionPolicy(action, context, cancellationToken);
}
public PolicyWrap<TResult> Wrap(ISyncPolicy innerPolicy)
{
if (innerPolicy == null)
throw new ArgumentNullException("innerPolicy");
return new PolicyWrap<TResult>((Func<Context, CancellationToken, TResult> func, Context context, CancellationToken cancellationtoken) => PolicyWrapEngine.Implementation<TResult>(func, context, cancellationtoken, (ISyncPolicy<TResult>)this, innerPolicy), this, innerPolicy);
}
public PolicyWrap<TResult> Wrap(ISyncPolicy<TResult> innerPolicy)
{
if (innerPolicy == null)
throw new ArgumentNullException("innerPolicy");
return new PolicyWrap<TResult>((Func<Context, CancellationToken, TResult> func, Context context, CancellationToken cancellationtoken) => PolicyWrapEngine.Implementation<TResult>(func, context, cancellationtoken, (ISyncPolicy<TResult>)this, innerPolicy), this, innerPolicy);
}
public PolicyWrap<TResult> WrapAsync(IAsyncPolicy innerPolicy)
{
if (innerPolicy == null)
throw new ArgumentNullException("innerPolicy");
return new PolicyWrap<TResult>((Func<Context, CancellationToken, Task<TResult>> func, Context context, CancellationToken cancellationtoken, bool continueOnCapturedContext) => PolicyWrapEngine.ImplementationAsync<TResult>(func, context, cancellationtoken, continueOnCapturedContext, (IAsyncPolicy<TResult>)this, innerPolicy), this, innerPolicy);
}
public PolicyWrap<TResult> WrapAsync(IAsyncPolicy<TResult> innerPolicy)
{
if (innerPolicy == null)
throw new ArgumentNullException("innerPolicy");
return new PolicyWrap<TResult>((Func<Context, CancellationToken, Task<TResult>> func, Context context, CancellationToken cancellationtoken, bool continueOnCapturedContext) => PolicyWrapEngine.ImplementationAsync<TResult>(func, context, cancellationtoken, continueOnCapturedContext, (IAsyncPolicy<TResult>)this, innerPolicy), this, innerPolicy);
}
}
}