Example #1
0
        /// <summary>
        /// Invoke the pipeline with the given input.
        /// </summary>
        /// <param name="invocation">Input to the method call.</param>
        /// <param name="throwOnException">Whether to throw the <see cref="IMethodReturn.Exception"/> if it has a value after running
        /// the behaviors.</param>
        /// <returns>Return value from the pipeline.</returns>
        public IMethodReturn Invoke(IMethodInvocation invocation, bool throwOnException = false)
        {
            IMethodReturn InvokeTargetOrThrow(IMethodInvocation invocation) => invocation.HasImplementation ?
            invocation.CreateInvokeReturn() :
            throw new NotImplementedException(ThisAssembly.Strings.NotImplemented(invocation));

            if (Behaviors.Count == 0)
            {
                return(InvokeTargetOrThrow(invocation));
            }

            // We convert to array so that the collection of behaviors can potentially
            // be modified by behaviors themselves for a subsequent pipeline execution.
            // The current pipeline execution, once started, cannot be modified, though.
            var behaviors = Behaviors.ToArray();

            var index = -1;

            for (var i = 0; i < behaviors.Length; i++)
            {
                if (!invocation.SkipBehaviors.Contains(behaviors[i].GetType()) && behaviors[i].AppliesTo(invocation))
                {
                    index = i;
                    break;
                }
            }

            if (index == -1)
            {
                return(InvokeTargetOrThrow(invocation));
            }

            ExecuteHandler GetNext()
            {
                for (index++; index < behaviors.Length; index++)
                {
                    if (!invocation.SkipBehaviors.Contains(behaviors[index].GetType()) && behaviors[index].AppliesTo(invocation))
                    {
                        break;
                    }
                }

                return((index < behaviors.Length) ?
                       behaviors[index].Execute :
                       (m, n) => InvokeTargetOrThrow(m));
            }

            var result = behaviors[index].Execute(invocation, (m, n) => GetNext().Invoke(m, n));

            if (throwOnException && result.Exception != null)
            {
                throw result.Exception;
            }

            return(result);
        }