/// <summary> /// This method executes the <see cref="IPipelineOperation{TContext}.Execute(TContext)"/> method of the specified /// <see cref="IPipelineOperation{TContext}"/> object passing it the <see cref="TContext"/> from the method parameter. /// </summary> /// <typeparam name="TOperation">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> Execute <TOperation>(TContext context) where TOperation : IPipelineOperation <TContext> { if (context == null) { throw new ArgumentException($"Parameter {typeof(TContext).Name} {nameof(context)} cannot be null", nameof(context)); } var opType = typeof(TOperation); if (context.EndProcessing) { context.ResultMessages.Add($"[{opType.Name}] Not Executed. A previous Operation terminated the operation pipeline."); return(this); } var operation = Operations[opType]; try { CheckDependencies(operation); } catch (OperationDependencyNotExecutedException ex) { context.EndProcessing = true; context.Exceptions.Add(ex); return(this); } try { operation.Execute(context); } catch (Exception ex) { context.Successful = false; context.Exceptions.Add(ex); if (ex is OperationExecutionException && !OperationsExecuted.Contains(opType)) { OperationsExecuted.Add(opType); } return(this); } if (!OperationsExecuted.Contains(opType)) { OperationsExecuted.Add(opType); } return(this); }
/// <summary> /// Adds the object specified by the <typeparamref name="TAsyncOperation"/> generic type to the <see cref="OperationTasks"/> /// collection to be awaited later asynchronously by one of the <see cref="WhenAll"/> methods /// </summary> /// <typeparam name="TAsyncOperation">The type of async operation that implements <see cref="IPipelineOperationAsync{TContext}"/></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> AddAsyncOperation <TAsyncOperation>(TContext context) where TAsyncOperation : IPipelineOperationAsync <TContext> { if (context == null) { throw new ArgumentException($"Parameter {typeof(TContext).Name} {nameof(context)} cannot be null", nameof(context)); } 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; OperationTasks.Add( 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 ) .ContinueWith( (task) => { context.Successful = false; context.Exceptions.Add(task.Exception); }, TaskContinuationOptions.OnlyOnFaulted ) ); return(this); }
/// <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); }