<PackageReference Include="Polly" Version="4.2.4" />

Policy

public class Policy
Transient exception handling policies that can be applied to delegates
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Polly { public class Policy { private readonly Action<Action, Context> _exceptionPolicy; private readonly IEnumerable<ExceptionPredicate> _exceptionPredicates; private readonly Func<Func<CancellationToken, Task>, Context, CancellationToken, bool, Task> _asyncExceptionPolicy; internal Policy(Action<Action> exceptionPolicy, IEnumerable<ExceptionPredicate> exceptionPredicates) : this(delegate(Action action, Context ctx) { exceptionPolicy(action); }, exceptionPredicates) { } internal Policy(Action<Action, Context> exceptionPolicy, IEnumerable<ExceptionPredicate> exceptionPredicates) { if (exceptionPolicy == null) throw new ArgumentNullException("exceptionPolicy"); _exceptionPolicy = exceptionPolicy; _exceptionPredicates = (exceptionPredicates ?? Enumerable.Empty<ExceptionPredicate>()); } [DebuggerStepThrough] public void Execute(Action action) { Execute(action, Context.Empty); } [DebuggerStepThrough] protected void Execute(Action action, Context context) { if (_exceptionPolicy == null) throw new InvalidOperationException("Please use the synchronous Retry, RetryForever, WaitAndRetry or CircuitBreaker methods when calling the synchronous Execute method."); _exceptionPolicy(action, context); } [DebuggerStepThrough] public PolicyResult ExecuteAndCapture(Action action) { return ExecuteAndCapture(action, Context.Empty); } [DebuggerStepThrough] protected PolicyResult ExecuteAndCapture(Action action, Context context) { if (_exceptionPolicy != null) try { _exceptionPolicy(action, context); return PolicyResult.Successful(); } catch (Exception exception) { return PolicyResult.Failure(exception, GetExceptionType(_exceptionPredicates, exception)); } throw new InvalidOperationException("Please use the synchronous Retry, RetryForever, WaitAndRetry or CircuitBreaker methods when calling the synchronous ExecuteAndCapture method."); } [DebuggerStepThrough] protected TResult Execute<TResult>(Func<TResult> action, Context context) { if (_exceptionPolicy == null) throw new InvalidOperationException("Please use the synchronous Retry, RetryForever, WaitAndRetry or CircuitBreaker methods when calling the synchronous Execute method."); TResult result = (TResult)default(TResult); _exceptionPolicy(delegate { result = (TResult)action(); }, context); return (TResult)result; } [DebuggerStepThrough] public TResult Execute<TResult>(Func<TResult> action) { return Execute(action, Context.Empty); } [DebuggerStepThrough] public PolicyResult<TResult> ExecuteAndCapture<TResult>(Func<TResult> action) { return ExecuteAndCapture(action, Context.Empty); } [DebuggerStepThrough] protected PolicyResult<TResult> ExecuteAndCapture<TResult>(Func<TResult> action, Context context) { if (_exceptionPolicy != null) try { TResult result = (TResult)default(TResult); _exceptionPolicy(delegate { result = (TResult)action(); }, context); return PolicyResult<TResult>.Successful((TResult)result); } catch (Exception exception) { return PolicyResult<TResult>.Failure(exception, GetExceptionType(_exceptionPredicates, exception)); } throw new InvalidOperationException("Please use the synchronous Retry, RetryForever, WaitAndRetry or CircuitBreaker methods when calling the synchronous ExecuteAndCapture method."); } public static PolicyBuilder Handle<TException>() where TException : Exception { return new PolicyBuilder((Exception exception) => exception is TException); } public static PolicyBuilder Handle<TException>(Func<TException, bool> exceptionPredicate) where TException : Exception { return new PolicyBuilder(delegate(Exception exception) { if (exception is TException) return exceptionPredicate((TException)exception); return false; }); } internal static ExceptionType GetExceptionType(IEnumerable<ExceptionPredicate> exceptionPredicates, Exception exception) { if (!exceptionPredicates.Any((ExceptionPredicate predicate) => predicate(exception))) return ExceptionType.Unhandled; return ExceptionType.HandledByThisPolicy; } internal Policy(Func<Func<CancellationToken, Task>, CancellationToken, bool, Task> asyncExceptionPolicy, IEnumerable<ExceptionPredicate> exceptionPredicates) : this((Func<CancellationToken, Task> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext) => asyncExceptionPolicy(action, cancellationToken, continueOnCapturedContext), exceptionPredicates) { } internal Policy(Func<Func<CancellationToken, Task>, Context, CancellationToken, bool, Task> asyncExceptionPolicy, IEnumerable<ExceptionPredicate> exceptionPredicates) { if (asyncExceptionPolicy == null) throw new ArgumentNullException("asyncExceptionPolicy"); _asyncExceptionPolicy = asyncExceptionPolicy; _exceptionPredicates = (exceptionPredicates ?? Enumerable.Empty<ExceptionPredicate>()); } [DebuggerStepThrough] public Task ExecuteAsync(Func<Task> action) { return ExecuteAsync(action, Context.Empty, false); } [DebuggerStepThrough] protected Task ExecuteAsync(Func<Task> action, Context context) { return ExecuteAsync(action, context, false); } [DebuggerStepThrough] public Task ExecuteAsync(Func<Task> action, bool continueOnCapturedContext) { return ExecuteAsync((CancellationToken ct) => action(), Context.Empty, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] protected Task ExecuteAsync(Func<Task> action, Context context, bool continueOnCapturedContext) { return ExecuteAsync((CancellationToken ct) => action(), context, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] public Task ExecuteAsync(Func<CancellationToken, Task> action, CancellationToken cancellationToken) { return ExecuteAsync(action, Context.Empty, cancellationToken, false); } [DebuggerStepThrough] protected Task ExecuteAsync(Func<CancellationToken, Task> action, Context context, CancellationToken cancellationToken) { return ExecuteAsync(action, context, cancellationToken, false); } [DebuggerStepThrough] public Task ExecuteAsync(Func<CancellationToken, Task> action, CancellationToken cancellationToken, bool continueOnCapturedContext) { return ExecuteAsync(action, Context.Empty, cancellationToken, continueOnCapturedContext); } protected async Task ExecuteAsync(Func<CancellationToken, Task> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext) { if (_asyncExceptionPolicy == null) throw new InvalidOperationException("Please use the asynchronous RetryAsync, RetryForeverAsync, WaitAndRetryAsync or CircuitBreakerAsync methods when calling the asynchronous Execute method."); await _asyncExceptionPolicy(action, context, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext); } [DebuggerStepThrough] public Task<PolicyResult> ExecuteAndCaptureAsync(Func<Task> action) { return ExecuteAndCaptureAsync(action, Context.Empty, false); } [DebuggerStepThrough] protected Task<PolicyResult> ExecuteAndCaptureAsync(Func<Task> action, Context context) { return ExecuteAndCaptureAsync(action, context, false); } [DebuggerStepThrough] public Task<PolicyResult> ExecuteAndCaptureAsync(Func<Task> action, bool continueOnCapturedContext) { return ExecuteAndCaptureAsync((CancellationToken ct) => action(), Context.Empty, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] protected Task<PolicyResult> ExecuteAndCaptureAsync(Func<Task> action, Context context, bool continueOnCapturedContext) { return ExecuteAndCaptureAsync((CancellationToken ct) => action(), context, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] public Task<PolicyResult> ExecuteAndCaptureAsync(Func<CancellationToken, Task> action, CancellationToken cancellationToken) { return ExecuteAndCaptureAsync(action, Context.Empty, cancellationToken, false); } [DebuggerStepThrough] protected Task<PolicyResult> ExecuteAndCaptureAsync(Func<CancellationToken, Task> action, Context context, CancellationToken cancellationToken) { return ExecuteAndCaptureAsync(action, context, cancellationToken, false); } [DebuggerStepThrough] public Task<PolicyResult> ExecuteAndCaptureAsync(Func<CancellationToken, Task> action, CancellationToken cancellationToken, bool continueOnCapturedContext) { return ExecuteAndCaptureAsync(action, Context.Empty, cancellationToken, continueOnCapturedContext); } protected async Task<PolicyResult> ExecuteAndCaptureAsync(Func<CancellationToken, Task> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext) { if (_asyncExceptionPolicy != null) try { await _asyncExceptionPolicy(action, context, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext); return PolicyResult.Successful(); } catch (Exception exception) { return PolicyResult.Failure(exception, GetExceptionType(_exceptionPredicates, exception)); } throw new InvalidOperationException("Please use the asynchronous RetryAsync, RetryForeverAsync, WaitAndRetryAsync or CircuitBreakerAsync methods when calling the asynchronous Execute method."); } [DebuggerStepThrough] public Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> action) { return ExecuteAsync(action, Context.Empty, false); } [DebuggerStepThrough] protected Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> action, Context context) { return ExecuteAsync(action, context, false); } [DebuggerStepThrough] public Task<TResult> ExecuteAsync<TResult>(Func<CancellationToken, Task<TResult>> action, CancellationToken cancellationToken) { return ExecuteAsync(action, Context.Empty, cancellationToken, false); } [DebuggerStepThrough] protected Task<TResult> ExecuteAsync<TResult>(Func<CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken) { return ExecuteAsync(action, context, cancellationToken, false); } [DebuggerStepThrough] public Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> action, bool continueOnCapturedContext) { return ExecuteAsync((CancellationToken ct) => action(), Context.Empty, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] protected Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> action, Context context, bool continueOnCapturedContext) { return ExecuteAsync((CancellationToken ct) => action(), context, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] public Task<TResult> ExecuteAsync<TResult>(Func<CancellationToken, Task<TResult>> action, CancellationToken cancellationToken, bool continueOnCapturedContext) { return ExecuteAsync(action, Context.Empty, cancellationToken, continueOnCapturedContext); } protected async Task<TResult> ExecuteAsync<TResult>(Func<CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext) { if (_asyncExceptionPolicy == null) throw new InvalidOperationException("Please use the asynchronous RetryAsync, RetryForeverAsync, WaitAndRetryAsync or CircuitBreakerAsync methods when calling the asynchronous Execute method."); TResult result = (TResult)default(TResult); await _asyncExceptionPolicy(async delegate(CancellationToken ct) { TResult val2 = result; TResult val = (TResult)(result = (TResult)(await action(ct).ConfigureAwait(continueOnCapturedContext))); }, context, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext); return (TResult)result; } [DebuggerStepThrough] public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<Task<TResult>> action) { return ExecuteAndCaptureAsync(action, Context.Empty, false); } [DebuggerStepThrough] protected Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<Task<TResult>> action, Context context) { return ExecuteAndCaptureAsync(action, context, false); } [DebuggerStepThrough] public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<Task<TResult>> action, bool continueOnCapturedContext) { return ExecuteAndCaptureAsync((CancellationToken ct) => action(), Context.Empty, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] protected Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<Task<TResult>> action, Context context, bool continueOnCapturedContext) { return ExecuteAndCaptureAsync((CancellationToken ct) => action(), context, CancellationToken.None, continueOnCapturedContext); } [DebuggerStepThrough] public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<Task<TResult>> action, CancellationToken cancellationToken) { return ExecuteAndCaptureAsync((CancellationToken ct) => action(), Context.Empty, cancellationToken, false); } [DebuggerStepThrough] protected Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<Task<TResult>> action, Context context, CancellationToken cancellationToken) { return ExecuteAndCaptureAsync((CancellationToken ct) => action(), context, cancellationToken, false); } [DebuggerStepThrough] public Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<CancellationToken, Task<TResult>> action, CancellationToken cancellationToken, bool continueOnCapturedContext) { return ExecuteAndCaptureAsync(action, Context.Empty, cancellationToken, continueOnCapturedContext); } protected async Task<PolicyResult<TResult>> ExecuteAndCaptureAsync<TResult>(Func<CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext) { if (_asyncExceptionPolicy != null) try { TResult result = (TResult)default(TResult); await _asyncExceptionPolicy(async delegate(CancellationToken ct) { TResult val2 = result; TResult val = (TResult)(result = (TResult)(await action(ct).ConfigureAwait(continueOnCapturedContext))); }, context, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext); return PolicyResult<TResult>.Successful((TResult)result); } catch (Exception exception) { return PolicyResult<TResult>.Failure(exception, GetExceptionType(_exceptionPredicates, exception)); } throw new InvalidOperationException("Please use the asynchronous RetryAsync, RetryForeverAsync, WaitAndRetryAsync or CircuitBreakerAsync methods when calling the asynchronous Execute method."); } } }