Example #1
0
        /// <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);
        }