/// <summary>
 /// Add a decorator to the enumerable for additional processing
 /// </summary>
 /// <param name="operation">The operation.</param>
 /// <param name="enumerator">The enumerator.</param>
 /// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> that may be used to cancel the asynchronous iteration.</param>
 protected override AsyncEnumerableTask <Row> DecorateEnumerableForExecution(
     IOperation operation,
     IAsyncEnumerable <Row> enumerator,
     CancellationToken cancellationToken = default)
 {
     return(AsyncEnumerableTask <Row> .Completed(new CachingEnumerable <Row>(new EventRaisingEnumerator(operation, enumerator), cancellationToken)));
 }
 /// <summary>
 /// Add a decorator to the enumerable for additional processing
 /// </summary>
 /// <param name="operation">The operation.</param>
 /// <param name="enumerator">The enumerator.</param>
 /// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> that may be used to cancel the asynchronous iteration.</param>
 protected override AsyncEnumerableTask <Row> DecorateEnumerableForExecution(IOperation operation,
                                                                             IAsyncEnumerable <Row> enumerator,
                                                                             CancellationToken cancellationToken = default)
 {
     return(AsyncEnumerableTask <Row> .Completed(new AsyncEnumerable <Row>(async yield =>
     {
         await new EventRaisingEnumerator(operation, enumerator)
         .ForEachAsync(async row => { await yield.ReturnAsync(row); }, cancellationToken);
     })));
 }
        /// <summary>
        /// Transform the pipeline to an enumerable
        /// </summary>
        /// <param name="pipeline">The pipeline.</param>
        /// <param name="rows">The rows</param>
        /// <param name="translateEnumerable">Translate the rows from one representation to another</param>
        /// <param name="cancellationToken">A CancellationToken to stop execution</param>
        /// <returns></returns>
        public virtual IAsyncEnumerable <Row> PipelineToEnumerable(
            ICollection <IOperation> pipeline,
            IAsyncEnumerable <Row> rows,
            Func <IAsyncEnumerable <Row>, IAsyncEnumerable <Row> > translateEnumerable,
            CancellationToken cancellationToken = default)
        {
            IList <Task> tasks = new List <Task>();

            foreach (var operation in pipeline)
            {
                operation.PrepareForExecution(this);
                var enumerator = operation.Execute(rows, cancellationToken);
                enumerator = translateEnumerable(enumerator);
                AsyncEnumerableTask <Row> task = DecorateEnumerableForExecution(operation, enumerator, cancellationToken);
                rows = task.Enumerable;
                tasks.Add(task.Task);
            }

            Task.WaitAll(tasks.ToArray());

            return(rows);
        }