/// <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(); }