public static Expression CallStringContains(ExpressionData exp, Expression ep) { var type = typeof(string); var mi = type.GetMethod("Contains"); if (mi == null) { throw new InvalidOperationException(); } return(Expression.Call(ep, mi, Expression.Constant(exp.Expression.Data, typeof(string)))); }
private static ConstantExpression BuildContains(ExpressionData exp, Expression ep) { Type dataType; switch (exp.Expression.DataType) { case DataType.Integer: dataType = typeof(int); break; case DataType.String: dataType = typeof(string); break; case DataType.Decimal: dataType = typeof(decimal); break; case DataType.Double: dataType = typeof(double); break; case DataType.Boolean: dataType = typeof(bool); break; case DataType.DateTime: dataType = typeof(DateTime); break; case DataType.Guid: dataType = typeof(Guid); break; case DataType.Enum: dataType = ep.Type; break; case DataType.Expression: case null: throw new InvalidOperationException(); default: throw new ArgumentOutOfRangeException(); } var generic = typeof(IEnumerable <>).MakeGenericType(dataType); var data = JsonConvert.SerializeObject(exp.Expression.Data); var typedData = JsonConvert.DeserializeObject(data, generic); return(Expression.Constant(typedData)); }
public static Expression CallContains(ExpressionData exp, Expression ep) { Expression property = BuildContains(exp, ep); var cType = GetIEnumerable(property.Type); var elemType = cType.GetGenericArguments()[0]; var action = (MethodInfo) GetGenericMethod(typeof(Enumerable), Action.Contains.ToString(), new[] { elemType }, new[] { cType, elemType }, BindingFlags.Static); property = Expression.Convert(property, cType); return(Expression.Call(action, property, ep)); }
private LambdaExpression BuildListCall(ExpressionData exp, Expression ep, string peParam) { var pi = ((MemberExpression)ep).Member as PropertyInfo; if (pi == null) { throw new InvalidOperationException(); } var type = pi.PropertyType.GenericTypeArguments[0]; var pe = Expression.Parameter(type, peParam); var json = JsonConvert.SerializeObject(exp.Expression.Data); var criteria = JsonConvert.DeserializeObject <Filter>(json); var be = BoolExpression(criteria, null, pe); var generic = typeof(Func <,>).MakeGenericType(type, typeof(bool)); return(Expression.Lambda(generic, be, pe)); }
private Expression CreateExpression(Expression parameterExpression, ExpressionData exp) { Expression ex; switch (exp.Type) { case ExpressionType.Condition: ex = BoolExpression(exp.Filter, null, parameterExpression); break; case ExpressionType.Expression: Expression ep; switch (exp.Expression.PropertyType) { case PropertyType.Value: case PropertyType.Collection: case PropertyType.Key: case PropertyType.BasicCollection: case PropertyType.StringContains: ep = BuilderUtility.GetProperty(parameterExpression, exp.Expression.PropertyId); break; case PropertyType.Method: ep = BuilderUtility.CallMethod(parameterExpression, exp, _methods); break; default: throw new ArgumentOutOfRangeException(); } ex = BuildExpression(ep, exp); break; default: throw new ArgumentOutOfRangeException(); } return(ex); }
public static Expression CallMethod( Expression parameterExpression, ExpressionData exp, IDictionary <string, IMethod> methods) { if (!methods.ContainsKey(exp.Expression.PropertyId)) { throw new InvalidOperationException("Unable to find method from method collection"); } var instance = methods[exp.Expression.PropertyId]; var type = instance.GetType(); var constant = Expression.Constant(instance, type); var mi = (MethodInfo) GetGenericMethod(typeof(IMethod), "Evaluate", new[] { parameterExpression.Type }, new[] { parameterExpression.Type }, BindingFlags.Instance); return(Expression.Call(constant, mi, parameterExpression)); }
public static ConstantExpression BuildConstantExpression( IDictionary <string, IToken> tokens, Expression property, ExpressionData exp, DataType dataType) { ConstantExpression ce; if (exp.Expression.Right == null && string.IsNullOrWhiteSpace(exp.Expression.Token)) { if (Nullable.GetUnderlyingType(property.Type) != null || dataType == DataType.String) { return(Expression.Constant(null)); } throw new InvalidOperationException("Constant value or token is missing"); } if (exp.Expression.Right != null && !string.IsNullOrWhiteSpace(exp.Expression.Token)) { throw new InvalidOperationException("Must specify a constant value or token but not both"); } if (!string.IsNullOrWhiteSpace(exp.Expression.Token) && !tokens.ContainsKey(exp.Expression.Token)) { throw new InvalidOperationException("Unable to find token from token collection"); } switch (dataType) { case DataType.Expression: throw new InvalidOperationException(); case DataType.Integer: ce = Expression.Constant( exp.Expression.Right != null ? Convert.ToInt32(exp.Expression.Right) : tokens[exp.Expression.Token].Value <int>(), typeof(int)); break; case DataType.String: ce = Expression.Constant( exp.Expression.Right != null ? Convert.ToString(exp.Expression.Right) : tokens[exp.Expression.Token].Value <string>(), typeof(string)); break; case DataType.Decimal: ce = Expression.Constant( exp.Expression.Right != null ? Convert.ToDecimal(exp.Expression.Right) : tokens[exp.Expression.Token].Value <decimal>(), typeof(decimal)); break; case DataType.Double: ce = Expression.Constant( exp.Expression.Right != null ? Convert.ToDouble(exp.Expression.Right) : tokens[exp.Expression.Token].Value <double>(), typeof(double)); break; case DataType.Boolean: ce = Expression.Constant( exp.Expression.Right != null ? Convert.ToBoolean(exp.Expression.Right) : tokens[exp.Expression.Token].Value <bool>(), typeof(bool)); break; case DataType.DateTime: ce = Expression.Constant( exp.Expression.Right != null ? Convert.ToDateTime(exp.Expression.Right) : tokens[exp.Expression.Token].Value <DateTime>(), typeof(DateTime)); break; case DataType.Guid: ce = Expression.Constant( exp.Expression.Right != null ? Guid.Parse(Convert.ToString(exp.Expression.Right)) : Guid.Parse(tokens[exp.Expression.Token].Value <string>()), typeof(Guid)); break; case DataType.Enum: var type = Nullable.GetUnderlyingType(property.Type); var enumType = Enum.GetUnderlyingType(type ?? property.Type); ce = Expression.Constant( exp.Expression.Right != null ? Convert.ChangeType(exp.Expression.Right, enumType) : Convert.ChangeType(tokens[exp.Expression.Token].Value <int>(), enumType)); break; default: throw new ArgumentOutOfRangeException(nameof(dataType), dataType, null); } return(ce); }
private Expression BuildExpression(Expression ep, ExpressionData exp) { Expression ex; var dataType = exp.Expression.Type; var ce = BuilderUtility.BuildConstantExpression(_tokens, ep, exp, dataType); var memberType = BuilderUtility.GetDataType(exp.Expression.Type, ep); switch (exp.Expression.PropertyType) { case PropertyType.Value: break; case PropertyType.Collection: case PropertyType.BasicCollection: ep = BuilderUtility.CallAction( exp.Expression.Action, ep, BuildListCall(exp, ep, $"f{_peCounter}")); _peCounter++; break; case PropertyType.Key: if (exp.Expression.Action == Action.Compare) { break; } if (exp.Expression.Action != Action.Contains) { throw new NotSupportedException(); } ep = BuilderUtility.CallContains(exp, ep); break; case PropertyType.Method: break; case PropertyType.StringContains: ep = BuilderUtility.CallStringContains(exp, ep); break; default: throw new ArgumentOutOfRangeException(); } switch (exp.Expression.Operator) { case Operator.Eq: ex = Expression.Equal(ep, Expression.Convert(ce, memberType)); break; case Operator.Neq: ex = Expression.NotEqual(ep, Expression.Convert(ce, memberType)); break; case Operator.Gt: ex = Expression.GreaterThan(ep, Expression.Convert(ce, memberType)); break; case Operator.Gte: ex = Expression.GreaterThanOrEqual(ep, Expression.Convert(ce, memberType)); break; case Operator.Lt: ex = Expression.LessThan(ep, Expression.Convert(ce, memberType)); break; case Operator.Lte: ex = Expression.LessThanOrEqual(ep, Expression.Convert(ce, memberType)); break; default: throw new ArgumentOutOfRangeException(); } return(ex); }