/// <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);
            }
        }
 /// <summary>
 /// Starts execution by using a specific object with a specific a contract.
 /// </summary>
 /// <param name="obj">The object to use.</param>
 /// <param name="contract">The contract.</param>
 /// <returns>The execution result.</returns>
 /// <exception cref="ArgumentNullException">
 /// <paramref name="obj" /> is <see langword="null" />.
 /// </exception>
 public object ExecuteFor(object obj, Type contract)
 {
     return(this.ExecuteFor(obj,
                            WorkflowAttributeBase.GetContractName(contract)));
 }