/// <summary>
        /// Returns the iterator for <see cref="WorkflowBase.GetEnumerator()" />.
        /// </summary>
        /// <param name="obj">The underlying object.</param>
        /// <param name="contractName">The name of the contract.</param>
        /// <returns>The iterator.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="obj" /> is <see langword="null" />.
        /// </exception>
        protected IEnumerable <WorkflowFunc> GetFunctionIterator(object obj, IEnumerable <char> contractName)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }

            string contract = WorkflowAttributeBase.ParseContractName(contractName);

            Type type = obj.GetType();
            IEnumerable <MethodInfo> allMethods = GetMethodsByType(type);

            List <Exception> occuredErrors = new List <Exception>();

            // find start method
            MethodInfo currentMethod = null;
            {
                IEnumerable <MethodInfo> methodsWithAttribs =
                    CollectionHelper.Where(allMethods,
                                           delegate(MethodInfo method)
                {
                    // search for 'ReceiveNotificationFromAttribute'
                    object[] attribs = method.GetCustomAttributes(typeof(global::MarcelJoachimKloubert.CLRToolbox.Execution.Workflows.WorkflowStartAttribute),
                                                                  true);

                    // strong typed sequence
                    IEnumerable <WorkflowStartAttribute> wfStartAttribs =
                        CollectionHelper.OfType <WorkflowStartAttribute>(attribs);

                    // filter by contract name
                    IEnumerable <WorkflowStartAttribute> wfStartAttribForMethod =
                        CollectionHelper.Where(wfStartAttribs,
                                               delegate(WorkflowStartAttribute a)
                    {
                        return(a.Contract == contract);
                    });

                    return(CollectionHelper.Any(wfStartAttribForMethod));
                });

                currentMethod = CollectionHelper.SingleOrDefault(methodsWithAttribs);
            }

            IDictionary <string, object> execVars = this.CreateVarStorage();
            bool hasBeenCanceled = false;
            long index           = -1;
            IReadOnlyDictionary <string, object> previousVars = null;
            object result      = null;
            object syncRoot    = new object();
            bool   throwErrors = true;

            while ((hasBeenCanceled == false) &&
                   (currentMethod != null))
            {
                yield return(delegate(object[] args)
                {
                    SimpleWorkflowExecutionContext ctx = new SimpleWorkflowExecutionContext();
                    ctx.Cancel = false;
                    ctx.ContinueOnError = false;
                    ctx.ExecutionArguments = new TMReadOnlyList <object>(args ?? new object[] { null });
                    ctx.ExecutionVars = execVars;
                    ctx.HasBeenCanceled = hasBeenCanceled;
                    ctx.Index = ++index;
                    ctx.NextVars = this.CreateVarStorage();
                    ctx.PreviousVars = previousVars;
                    ctx.Result = result;
                    ctx.SyncRoot = syncRoot;
                    ctx.ThrowErrors = throwErrors;
                    ctx.Workflow = this;
                    ctx.WorkflowVars = this.Vars;

                    // first try to find method for next step
                    MethodInfo nextMethod = null;
                    {
                        // search for 'NextWorkflowStepAttribute'
                        object[] attribs = currentMethod.GetCustomAttributes(typeof(global::MarcelJoachimKloubert.CLRToolbox.Execution.Workflows.NextWorkflowStepAttribute),
                                                                             true);

                        // strong typed sequence
                        IEnumerable <NextWorkflowStepAttribute> nextStepAttribs = CollectionHelper.OfType <NextWorkflowStepAttribute>(attribs);

                        // filter by contract name
                        NextWorkflowStepAttribute nextStep = CollectionHelper.SingleOrDefault(nextStepAttribs,
                                                                                              delegate(NextWorkflowStepAttribute a)
                        {
                            return a.Contract == contract;
                        });

                        if (nextStep != null)
                        {
                            IEnumerable <MethodInfo> nextMethods = CollectionHelper.Where(allMethods,
                                                                                          delegate(MethodInfo m)
                            {
                                return m.Name == nextStep.Member;
                            });

                            // first: try find with parameter
                            nextMethod = CollectionHelper.SingleOrDefault(nextMethods,
                                                                          delegate(MethodInfo m)
                            {
                                return m.GetParameters().Length > 0;
                            });

                            if (nextMethod == null)
                            {
                                // first: now find WITHOUT parameter
                                nextMethod = CollectionHelper.Single(nextMethods,
                                                                     delegate(MethodInfo m)
                                {
                                    return m.GetParameters().Length < 1;
                                });
                            }
                        }
                    }

                    // execution
                    InvokeWorkflowMethod(obj, currentMethod,
                                         ctx,
                                         occuredErrors);

                    WorkflowActionNoState nextAction = ctx.Next;
                    if (nextAction == null)
                    {
                        currentMethod = nextMethod;
                    }
                    else
                    {
                        obj = nextAction.Target;
                        currentMethod = nextAction.Method;

                        type = currentMethod.ReflectedType;
                        allMethods = GetMethodsByType(type);
                    }

                    previousVars = new TMReadOnlyDictionary <string, object>(ctx.NextVars);
                    throwErrors = ctx.ThrowErrors;

                    if (ctx.Cancel)
                    {
                        hasBeenCanceled = true;
                        ctx.HasBeenCanceled = hasBeenCanceled;
                    }

                    return ctx;
                });
            }

            if (throwErrors &&
                (occuredErrors.Count > 0))
            {
                throw new AggregateException(occuredErrors);
            }
        }
        // Protected Methods (1) 

        /// <summary>
        /// Returns the iterator for <see cref="WorkflowBase.GetEnumerator()" />.
        /// </summary>
        /// <typeparam name="S">Type of the state object.</typeparam>
        /// <param name="startAction">The start action.</param>
        /// <param name="actionStateFactory">The function that provides the state object for <paramref name="startAction" />.</param>
        /// <returns>The iterator.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="startAction" /> and/or <paramref name="actionStateFactory" /> are <see langword="null" />.
        /// </exception>
        protected IEnumerable <WorkflowFunc> GetFunctionIterator <S>(WorkflowAction <S> startAction, Func <long, S> actionStateFactory)
        {
            if (startAction == null)
            {
                throw new ArgumentNullException("startAction");
            }

            if (actionStateFactory == null)
            {
                throw new ArgumentNullException("actionStateFactory");
            }

            List <Exception> occuredErrors = new List <Exception>();

            WorkflowAction <S>           currentAction = startAction;
            IDictionary <string, object> execVars      = this.CreateVarStorage();
            bool hasBeenCanceled = false;
            long index           = -1;
            IReadOnlyDictionary <string, object> previousVars = null;
            object result      = null;
            object syncRoot    = new object();
            bool   throwErrors = true;

            while ((hasBeenCanceled == false) &&
                   (currentAction != null))
            {
                yield return(delegate(object[] args)
                {
                    SimpleWorkflowExecutionContext <S> ctx = new SimpleWorkflowExecutionContext <S>();
                    ctx.Cancel = false;
                    ctx.ContinueOnError = false;
                    ctx.ExecutionArguments = new TMReadOnlyList <object>(args ?? new object[] { null });
                    ctx.ExecutionVars = execVars;
                    ctx.HasBeenCanceled = hasBeenCanceled;
                    ctx.Index = ++index;
                    ctx.Next = null;
                    ctx.NextVars = this.CreateVarStorage();
                    ctx.PreviousVars = previousVars;
                    ctx.Result = result;
                    ctx.State = actionStateFactory(ctx.Index);
                    ctx.SyncRoot = syncRoot;
                    ctx.ThrowErrors = throwErrors;
                    ctx.Workflow = this;
                    ctx.WorkflowVars = this.Vars;

                    // execution
                    try
                    {
                        currentAction(ctx);

                        result = ctx.Result;
                    }
                    catch (Exception ex)
                    {
                        occuredErrors.Add(ex);

                        if (ctx.ContinueOnError == false)
                        {
                            throw;
                        }
                    }

                    previousVars = new TMReadOnlyDictionary <string, object>(ctx.NextVars);
                    throwErrors = ctx.ThrowErrors;

                    currentAction = ((IWorkflowExecutionContext <S>)ctx).Next;

                    if (ctx.Cancel)
                    {
                        hasBeenCanceled = true;
                        ctx.HasBeenCanceled = hasBeenCanceled;
                    }

                    return ctx;
                });
            }

            if (throwErrors &&
                (occuredErrors.Count > 0))
            {
                throw new AggregateException(occuredErrors);
            }
        }