public void CloneReturnsEqualObject()
        {
            // Arrange
            var evaluatedDataTypes = new List<Type> { typeof(int), typeof(char), typeof(DateTime) };
            var context = new ExpressionCreationContext() {
                    CurrentDepth = 10,
                    RequestedReturnType = typeof(int),
                };

            // Use reflection to inject evaluatedDataTypes
            typeof(ExpressionCreationContext).GetField("evaluatedDataTypes", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(context, evaluatedDataTypes);

            // Act
            var cloned = context.Clone();

            // Assert
            Assert.AreNotSame(cloned, context); // Not the same reference.
            Assert.AreEqual(10, cloned.CurrentDepth);
            Assert.AreEqual(typeof(int), cloned.RequestedReturnType);
            Assert.AreEqual(evaluatedDataTypes, cloned.EvaluatedDataTypes);
        }
        /// <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;
        }
Exemplo n.º 3
0
        /// <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();
        }