/// <summary>
 /// Returns the strictest ExpressionCreationConditions union from the two values.
 /// </summary>
 /// <param name="val1">The first value.</param>
 /// <param name="val2">The second value.</param>
 /// <returns>Strictest ExpressionCreationConditions made from two values.</returns>
 internal static ExpressionCreationConditions StrictestUnion(ExpressionCreationConditions val1, ExpressionCreationConditions val2)
 {
     var min = new ExpressionCreationConditions(maxDepth: Math.Min(val1.MaxDepth, val2.MaxDepth)) {
          RequestedReturnType = val1.RequestedReturnType ?? val2.RequestedReturnType
     };
     return min;
 }
        /// <summary>
        /// Determines whether this instance can create an object of the specified type.
        /// </summary>
        /// <param name="conditions">The conditions of expression evaluation when creating expression.</param>
        /// <param name="context">The context of expression evaluation when creating expression.</param>
        /// <returns>
        /// <c>true</c> if this instance an object of the specified type; otherwise, <c>false</c>.
        /// </returns>
        public bool CanCreate(ExpressionCreationConditions conditions, ExpressionCreationContext context)
        {
            if (context == null) {
                throw new ArgumentNullException("context");
            }

            return this.CanCreateInternal(context.RequestedReturnType);
        }
 /// <summary>
 /// Creates a new the expression with specific expression type.
 /// </summary>
 /// <param name="requestedType">The requested type of the root expression.</param>
 /// <param name="creationConditions">The creation conditions.</param>
 /// <param name="creationContext">The context of the creation evaluation.</param>
 /// <returns>New random expression.</returns>
 private Expression NewExpressionInternal(ExpressionType requestedType, ExpressionCreationConditions creationConditions, ExpressionCreationContext creationContext)
 {
     ExpressionCreationConditions strictest = ExpressionCreationConditions.StrictestUnion(this.CreationConditions, creationConditions);
     Expression expression = this.ExpressionCreator.CreateInternal(requestedType, strictest, creationContext);
     return expression;
 }
        /// <summary>
        /// Creates a new random expression.
        /// </summary>
        /// <remarks>
        /// Tries to feed all the expression types into the expresssion
        /// creator until an expresssion is successfully created.
        /// </remarks>
        /// <param name="conditions">The creation conditions.</param>
        /// <param name="creationContext">The context of the creation evaluation.</param>
        /// <returns>New random expression.</returns>
        private Expression NewExpression(ExpressionCreationConditions conditions, ExpressionCreationContext creationContext)
        {
            List<ExpressionType> failedExpressionTypes = null;
            ExpressionType randomType = default(ExpressionType);

            ExpressionCreationContext currentContext = creationContext.Clone();
            if (currentContext.RequestedReturnType == null) {
                // Our current expression context requested type is the builder's requested type.
                currentContext.RequestedReturnType = conditions.RequestedReturnType;
            }

            Expression newExpression;

            // TODO: Ignore: You WERE HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            for (;;) {
                try {
                    for (;;) {
                        // TODO: This block will loop indefinitely unless we detect when valid expression types are exhausted.
                        randomType = this.NewExpressionTypeProvider.NextExpressionType();

                        /* If this expression type has not failed yet, try it. */
                        if (failedExpressionTypes == null || !failedExpressionTypes.Contains(randomType)) {
                            break;
                        }
                    }

                    newExpression = this.NewExpressionInternal(randomType, conditions, currentContext);
                    break;
                } catch (ExpressionCreationException) {
                    /* If failed, try another expression type. */
                    if (failedExpressionTypes == null) {
                        failedExpressionTypes = new List<ExpressionType>();
                    }

                    failedExpressionTypes.Add(randomType);
                }
            }

            return newExpression;
        }
 /// <summary>
 /// Creates a new the expression with specific expression type.
 /// </summary>
 /// <remarks>
 /// This method is really only meant for tests, so this will throw an exception if it can't succeed.
 /// </remarks>
 /// <param name="requestedType">The requested type of the root expression.</param>
 /// <param name="creationConditions">The creation conditions.</param>
 /// <returns>New random expression.</returns>
 public Expression NewExpression(ExpressionType requestedType, ExpressionCreationConditions creationConditions)
 {
     try {
         Expression result = this.NewExpressionInternal(requestedType, creationConditions, new ExpressionCreationContext());
         return result;
     } catch (Exception e) {
         throw new ExpressionCreationException(string.Format(CultureInfo.InvariantCulture, "Expression of type {0} could not be created", requestedType), e);
     }
 }
        private Expression CreateObjectExpression(ExpressionCreationConditions conditions, ExpressionCreationContext creationContext)
        {
            /* Check that we can create the object (for performance reasons), and create the object. */
            if (this.NewObjectCreator.CanCreate(conditions, creationContext)) {
                return Expression.Constant(this.NewObjectCreator.CreateObject(conditions, creationContext));
            }

            /*
             * By default, return null if we can't create an object.
             * There is also not way to alert the caller that this call couldn't create the object.
             * Future: We could throw an exception, but the caller code could recover.
             */
            return Expression.Constant(null);
        }
 private Expression CreateExpression(Func<Expression, Expression, Expression> expressionMethod, ExpressionCreationConditions conditions, ExpressionCreationContext creationContext)
 {
     Expression arg1 = this.NewExpressionCallback(conditions, creationContext);
     creationContext.EvaluatedDataTypes.Add(arg1.Type);
     Expression arg2 = this.NewExpressionCallback(conditions, creationContext);
     return expressionMethod(arg1, arg2);
 }
        /// <summary>
        /// Internal method that creates the expression that is of the specified expression type.
        /// </summary>
        /// <param name="expressionType">The expresion type to create.</param>
        /// <param name="conditions">The creation conditions.</param>
        /// <param name="creationContext">The context of the creation evaluation.</param>
        /// <returns>Created expression type.</returns>
        internal Expression CreateInternal(ExpressionType expressionType, ExpressionCreationConditions conditions, ExpressionCreationContext creationContext)
        {
            // If we have reached our max depth, then we can only create a depth that gaurentees 1 depth.
            if (conditions.MaxDepth == creationContext.CurrentDepth) {
                expressionType = ExpressionType.Constant;
            }

            /* Increment depth count. */
            creationContext.CurrentDepth++;

            try {
                switch (expressionType) {
                    case ExpressionType.Add:
                        return this.CreateExpression(Expression.Add, conditions, creationContext);
                        ////return Expression.Add(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.AddChecked:
                        return this.CreateExpression(Expression.AddChecked, conditions, creationContext);
                        ////return Expression.AddChecked(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.And:
                        return Expression.And(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.AndAlso:
                        return Expression.AndAlso(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.ArrayLength:
                        return Expression.ArrayLength(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.ArrayIndex:
                        return Expression.ArrayIndex(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.Call:
                    ////    ////return Expression.Call(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Coalesce:
                        return Expression.Coalesce(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Conditional:
                        return Expression.Condition(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Constant:
                        return this.CreateObjectExpression(conditions, creationContext);
                    ////case ExpressionType.Convert:
                    ////    ////return Expression.Convert(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.ConvertChecked:
                    ////    ////return Expression.ConvertChecked(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Divide:
                        return Expression.Divide(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Equal:
                        return Expression.Equal(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.ExclusiveOr:
                        return Expression.ExclusiveOr(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.GreaterThan:
                        return Expression.GreaterThan(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.GreaterThanOrEqual:
                        return Expression.GreaterThanOrEqual(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Invoke:
                        return Expression.Invoke(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.Lambda:
                    ////    ////return Expression.Lambda(this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.LeftShift:
                        return Expression.LeftShift(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.LessThan:
                        return Expression.LessThan(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.LessThanOrEqual:
                        return Expression.LessThanOrEqual(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.ListInit:
                    ////    ////return Expression.ListInit(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.MemberAccess:
                    ////    ////return Expression.MakeMemberAccess(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.MemberInit:
                    ////    ////return Expression.MemberInit(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Modulo:
                        return Expression.Modulo(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Multiply:
                        return Expression.Multiply(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.MultiplyChecked:
                        return Expression.MultiplyChecked(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Negate:
                        return Expression.Negate(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.UnaryPlus:
                        return Expression.UnaryPlus(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.NegateChecked:
                        return Expression.NegateChecked(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.New:
                    ////    ////return Expression.New(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.NewArrayInit:
                    ////    ////return Expression.NewArrayInit(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.NewArrayBounds:
                    ////    ////return Expression.NewArrayBounds(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Not:
                        return Expression.Not(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.NotEqual:
                        return Expression.NotEqual(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Or:
                        return Expression.Or(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.OrElse:
                        return Expression.OrElse(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.Parameter:
                    ////    ////return Expression.Parameter(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Power:
                        return Expression.Power(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Quote:
                        return Expression.Quote(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.RightShift:
                        return Expression.RightShift(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Subtract:
                        return Expression.Subtract(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.SubtractChecked:
                        return Expression.SubtractChecked(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.TypeAs:
                    ////    ////return Expression.TypeAs(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.TypeIs:
                    ////    ////return Expression.TypeIs(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Assign:
                        return Expression.Assign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Block:
                        return Expression.Block(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.DebugInfo:
                    ////    ////return Expression.DebugInfo(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Decrement:
                        return Expression.Decrement(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.Dynamic:
                    ////    ////return Expression.Dynamic(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.Default:
                    ////    ////return Expression.Default(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.Extension:
                    ////    ////return Expression(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.Goto:
                    ////    ////return Expression.Goto(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Increment:
                        return Expression.Increment(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.Index:
                    ////    ////return Expression.MakeIndex(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.Label:
                    ////    ////return Expression.Label(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.RuntimeVariables:
                    ////    ////return Expression.RuntimeVariables(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.Loop:
                        return Expression.Loop(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Switch:
                        return Expression.Switch(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Throw:
                        return Expression.Throw(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.Try:
                    ////    ////return Expression.MakeTry(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.Unbox:
                    ////    ////return Expression.Unbox(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    ////case ExpressionType.AddAssign:
                    ////    return Expression.AddAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.AndAssign:
                    ////    return Expression.AndAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.DivideAssign:
                    ////    return Expression.DivideAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.ExclusiveOrAssign:
                    ////    return Expression.ExclusiveOrAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.LeftShiftAssign:
                    ////    return Expression.LeftShiftAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.ModuloAssign:
                    ////    return Expression.ModuloAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.MultiplyAssign:
                    ////    return Expression.MultiplyAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.OrAssign:
                    ////    return Expression.OrAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.PowerAssign:
                    ////    return Expression.PowerAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.RightShiftAssign:
                    ////    return Expression.RightShiftAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.SubtractAssign:
                    ////    return Expression.SubtractAssign(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.AddAssignChecked:
                    ////    return Expression.AddAssignChecked(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.MultiplyAssignChecked:
                    ////    return Expression.MultiplyAssignChecked(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.SubtractAssignChecked:
                    ////    return Expression.SubtractAssignChecked(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.PreIncrementAssign:
                    ////    return Expression.PreIncrementAssign(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.PreDecrementAssign:
                    ////    return Expression.PreDecrementAssign(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.PostIncrementAssign:
                    ////    return Expression.PostIncrementAssign(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.PostDecrementAssign:
                    ////    return Expression.PostDecrementAssign(this.NewExpressionCallback(conditions, creationContext));
                    ////case ExpressionType.TypeEqual:
                    ////    ////return Expression.TypeEqual(this.NewExpressionCallback(conditions, creationContext), this.NewExpressionCallback(conditions, creationContext));
                    ////    throw new NotImplementedException();
                    case ExpressionType.OnesComplement:
                        return Expression.OnesComplement(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.IsTrue:
                        return Expression.IsTrue(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.IsFalse:
                        return Expression.IsFalse(this.NewExpressionCallback(conditions, creationContext));
                    case ExpressionType.Call:
                    case ExpressionType.Convert:
                    case ExpressionType.ConvertChecked:
                    case ExpressionType.Lambda:
                    case ExpressionType.ListInit:
                    case ExpressionType.MemberAccess:
                    case ExpressionType.MemberInit:
                    case ExpressionType.New:
                    case ExpressionType.NewArrayInit:
                    case ExpressionType.NewArrayBounds:
                    case ExpressionType.Parameter:
                    case ExpressionType.TypeAs:
                    case ExpressionType.TypeIs:
                    case ExpressionType.DebugInfo:
                    case ExpressionType.Dynamic:
                    case ExpressionType.Default:
                    case ExpressionType.Extension:
                    case ExpressionType.Goto:
                    case ExpressionType.Index:
                    case ExpressionType.Label:
                    case ExpressionType.RuntimeVariables:
                    case ExpressionType.Try:
                    case ExpressionType.Unbox:
                    case ExpressionType.AddAssign:
                    case ExpressionType.AndAssign:
                    case ExpressionType.DivideAssign:
                    case ExpressionType.ExclusiveOrAssign:
                    case ExpressionType.LeftShiftAssign:
                    case ExpressionType.ModuloAssign:
                    case ExpressionType.MultiplyAssign:
                    case ExpressionType.OrAssign:
                    case ExpressionType.PowerAssign:
                    case ExpressionType.RightShiftAssign:
                    case ExpressionType.SubtractAssign:
                    case ExpressionType.AddAssignChecked:
                    case ExpressionType.MultiplyAssignChecked:
                    case ExpressionType.SubtractAssignChecked:
                    case ExpressionType.PreIncrementAssign:
                    case ExpressionType.PreDecrementAssign:
                    case ExpressionType.PostIncrementAssign:
                    case ExpressionType.PostDecrementAssign:
                    case ExpressionType.TypeEqual:
                    // Fine.
                    default:
                        throw new InvalidOperationException();
                }
            } catch (Exception e) {
                throw new ExpressionCreationException(string.Format(CultureInfo.InvariantCulture, "Expression of type {0} could not be created", expressionType), e);
            }
        }
        /// <summary>
        /// Creates the object of the specified type.
        /// </summary>
        /// <param name="conditions">The conditions of expression evaluation when creating expression.</param>
        /// <param name="context">The context of expression evaluation when creating expression.</param>
        /// <returns>Object of type.</returns>
        public object CreateObject(ExpressionCreationConditions conditions, ExpressionCreationContext context)
        {
            if (conditions == null) {
                throw new ArgumentNullException("conditions");
            }

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

            if (context.RequestedReturnType == null) {
                throw new ArgumentException("context");
            }

            if (!this.TypeRepository.HasType(context.RequestedReturnType)) {
                throw new ObjectCreationException();
            }

            foreach (MethodInfo method in this.TypeRepository.GetMethods(context.RequestedReturnType)) {
                ParameterInfo[] parameters = method.GetParameters();
                Func<object> callableAction = null;

                if (parameters.Length == 0) {
                    callableAction = () => {
                        return method.Invoke(null, null);
                    };
                } else if (conditions.MaxDepth > context.CurrentDepth) {
                    bool methodCreatable = true;

                    foreach (ParameterInfo parameter in parameters) {
                        if (!this.CanCreateInternal(parameter.ParameterType)) {
                            methodCreatable = false;
                            break;
                        }
                    }

                    if (methodCreatable) {
                        callableAction = () => {
                            object[] parameterObjects = new object[parameters.Length];
                            for (int i = 0; i < parameters.Length; i++) {
                                var evaluationContext = context.Clone();
                                evaluationContext.CurrentDepth++;
                                evaluationContext.RequestedReturnType = parameters[i].ParameterType;
                                parameterObjects[i] = this.CreateObject(conditions, evaluationContext);
                            }

                            return method.Invoke(null, parameterObjects);
                        };
                    }
                }

                if (callableAction != null) {
                    try {
                        /* Try to call method and return the result. */
                        object result = callableAction();
                        return result;
                    } catch (Exception ex) {
                        if (ex is TargetInvocationException || ex is ObjectCreationException) {
                            /* Add to our list of exceptions and continue looking for next. */
                            context.EvaluationExceptions.Add(ex);
                            continue;
                        } else {
                            // TODO
                            throw;
                        }
                    }
                }
            }

            throw new ObjectCreationException();
        }