/// <summary> /// This method executes the <see cref="IPipelineOperationAsync{TContext}.ExecuteAsync"/> method of the specified /// <see cref="IPipelineOperationAsync{TContext}"/> object passing it the <see cref="TContext"/> from the method parameter /// from the <see cref="Context"/> property. /// </summary> /// <typeparam name="TAsyncOperation">The object that will be used to process the <see cref="TContext"/> object</typeparam> /// <param name="context">The state object that will be acted upon</param> /// <returns><see cref="IPipelineCoordinator{TContext}"/> for dot chaining</returns> public virtual IPipelineCoordinator <TContext> ExecuteAsync <TAsyncOperation>(TContext context) where TAsyncOperation : IPipelineOperationAsync <TContext> { if (context == null) { throw new ArgumentException($"Parameter {typeof(TContext).Name} {nameof(context)} cannot be null", nameof(context)); } if (OperationTasks.Any()) { throw new OperationExecutionException($"Cannot execute individual await Operation while other Operation Tasks are pending. Execute the {nameof(WhenAll)} method to clear the pending Operation Tasks first."); } var opType = typeof(TAsyncOperation); if (context.EndProcessing) { context.ResultMessages.Add($"[{opType.Name}] Not Executed. A previous Operation terminated the operation pipeline."); return(this); } var operation = AsyncOperations[opType]; try { CheckDependencies(operation); } catch (OperationDependencyNotExecutedException ex) { context.EndProcessing = true; context.Exceptions.Add(ex); return(this); } operation.Context = context; var operationTask = operation .ExecuteAsync() .ContinueWith(task => { try { operation.CompletedTaskCallback(task); if (!OperationsExecuted.Contains(opType)) { OperationsExecuted.Add(opType); } } catch (Exception ex) { context.Successful = false; context.Exceptions.Add(ex); if (ex is OperationExecutionException && !OperationsExecuted.Contains(opType)) { OperationsExecuted.Add(opType); } } }, TaskContinuationOptions.OnlyOnRanToCompletion); try { operationTask.Wait(); } catch (Exception ex) { context.Successful = false; context.Exceptions.Add(ex); if (ex is OperationExecutionException && !OperationsExecuted.Contains(opType)) { OperationsExecuted.Add(opType); } } return(this); }