private readonly Dictionary <ExpressionNodeType, Func <ExpressionNode, Expression> > expressionAction; // Templates. #region ctor /// <summary> /// Creates a new instance of <see cref="ExpressionBuilder{T, TResult}"/>. /// </summary> public ExpressionBuilder() { this.ItemType = typeof(T); this.Properties = ItemType.GetCachedProperties(); this.ParameterExpression = Expression.Parameter(this.ItemType, "item"); expressionAction = new Dictionary <ExpressionNodeType, Func <ExpressionNode, Expression> >() { { ExpressionNodeType.RelationalOperator, BuildRelationalExpression }, { ExpressionNodeType.ArithmeticOperator, BuildArithmeticExpression }, { ExpressionNodeType.LogicalOperator, BuildLogicalOperator }, { ExpressionNodeType.PropertyType, BuildValueExpression }, { ExpressionNodeType.StringType, BuildValueExpression }, { ExpressionNodeType.DateType, BuildValueExpression }, { ExpressionNodeType.UnknownType, BuildValueExpression } }; }
/// <summary> /// Converts from <see cref="ExpressionNode"/> to <see cref="Expression"/> /// when the <see cref="ExpressionOperatorType"/> is a value expression. /// </summary> private Expression BuildValueExpression(ExpressionNode expression, ExpressionNodeType type) { Expression rdo; string content; PropertyInfo pi; content = expression.FormattedText ?? expression.Text; switch (type) { case ExpressionNodeType.StringType: if (content.StartsWith("'") && content.EndsWith("'")) { content = content.Substring(1, content.Length - 2); } rdo = Expression.Constant(content); break; case ExpressionNodeType.DateType: if (content.StartsWith("#") && content.EndsWith("#")) { content = content.Substring(1, content.Length - 2); } rdo = Expression.Constant(DateTime.Parse(content, CultureInfo.InvariantCulture)); break; case ExpressionNodeType.PropertyType: if (content.StartsWith("[") && content.EndsWith("]")) { content = content.Substring(1, content.Length - 2); } pi = ItemType.GetCachedProperties()[content]; rdo = Expression.Property(this.ParameterExpression, pi); break; case ExpressionNodeType.UnknownType: Double dbl; bool bln; // Adivinar tipo. Probar número, boolean, propiedad... Al final, si no se identifica, dejar como object. if (Double.TryParse(content, NumberStyles.Number, CultureInfo.InvariantCulture, out dbl)) { rdo = Expression.Constant(dbl); } else if (Boolean.TryParse(content, out bln)) { rdo = Expression.Constant(bln); } else if (Properties.TryGetValue(content, out pi)) { rdo = BuildValueExpression(expression, ExpressionNodeType.PropertyType); } else { rdo = Expression.Constant(content, typeof(object)); // TODO: Mas averiguaciones. } break; default: throw new NotImplementedException(); // TODO: Tipo no permitido. } return(rdo); }