private Query VisitExpression(Expression expr, string prefix = null) { // Single: x.Active if (expr is MemberExpression && expr.Type == typeof(bool)) { return(Query.EQ(this.GetField(expr, prefix), new BsonValue(true))); } // Not: !x.Active or !(x.Id == 1) else if (expr.NodeType == ExpressionType.Not) { var unary = expr as UnaryExpression; return(Query.Not(this.VisitExpression(unary.Operand, prefix))); } // Equals: x.Id == 1 else if (expr.NodeType == ExpressionType.Equal) { var bin = expr as BinaryExpression; return(new QueryEquals(this.GetField(bin.Left, prefix), this.VisitValue(bin.Right, bin.Left))); } // NotEquals: x.Id != 1 else if (expr.NodeType == ExpressionType.NotEqual) { var bin = expr as BinaryExpression; return(Query.Not(this.GetField(bin.Left, prefix), this.VisitValue(bin.Right, bin.Left))); } // LessThan: x.Id < 5 else if (expr.NodeType == ExpressionType.LessThan) { var bin = expr as BinaryExpression; return(Query.LT(this.GetField(bin.Left, prefix), this.VisitValue(bin.Right, bin.Left))); } // LessThanOrEqual: x.Id <= 5 else if (expr.NodeType == ExpressionType.LessThanOrEqual) { var bin = expr as BinaryExpression; return(Query.LTE(this.GetField(bin.Left, prefix), this.VisitValue(bin.Right, bin.Left))); } // GreaterThan: x.Id > 5 else if (expr.NodeType == ExpressionType.GreaterThan) { var bin = expr as BinaryExpression; return(Query.GT(this.GetField(bin.Left, prefix), this.VisitValue(bin.Right, bin.Left))); } // GreaterThanOrEqual: x.Id >= 5 else if (expr.NodeType == ExpressionType.GreaterThanOrEqual) { var bin = expr as BinaryExpression; return(Query.GTE(this.GetField(bin.Left, prefix), this.VisitValue(bin.Right, bin.Left))); } // And: x.Id > 1 && x.Name == "John" else if (expr.NodeType == ExpressionType.AndAlso) { var bin = expr as BinaryExpression; var left = this.VisitExpression(bin.Left, prefix); var right = this.VisitExpression(bin.Right, prefix); return(Query.And(left, right)); } // Or: x.Id == 1 || x.Name == "John" else if (expr.NodeType == ExpressionType.OrElse) { var bin = expr as BinaryExpression; var left = this.VisitExpression(bin.Left); var right = this.VisitExpression(bin.Right); return(Query.Or(left, right)); } // Constant: do nothing (at this point it's useful only to PredicateBuilder) else if (expr.NodeType == ExpressionType.Constant) { var constant = expr as ConstantExpression; if (constant.Value is bool) { var value = (bool)constant.Value; return(value ? Query.All() : new QueryEmpty()); } } // Invoke: call inner Lambda expression (used in PredicateBuilder) else if (expr.NodeType == ExpressionType.Invoke) { var invocation = expr as InvocationExpression; var lambda = invocation.Expression as LambdaExpression; return(this.VisitExpression(lambda.Body)); } // MethodCall: x.Name.StartsWith("John") else if (expr is MethodCallExpression) { var met = expr as MethodCallExpression; var method = met.Method.Name; #if NET35 var type = met.Method.ReflectedType; #else var type = met.Method.DeclaringType; #endif var paramType = met.Arguments[0] is MemberExpression ? (ExpressionType?)(met.Arguments[0] as MemberExpression).Expression.NodeType : null; // StartsWith if (method == "StartsWith") { var value = this.VisitValue(met.Arguments[0], null); return(Query.StartsWith(this.GetField(met.Object, prefix), value)); } // Equals else if (method == "Equals") { var value = this.VisitValue(met.Arguments[0], null); return(Query.EQ(this.GetField(met.Object, prefix), value)); } // Contains (String): x.Name.Contains("auricio") else if (method == "Contains" && type == typeof(string)) { var value = this.VisitValue(met.Arguments[0], null); return(Query.Contains(this.GetField(met.Object, prefix), value)); } // Contains (Enumerable): x.ListNumber.Contains(2) else if (method == "Contains" && type == typeof(Enumerable)) { var field = this.GetField(met.Arguments[0], prefix); var value = this.VisitValue(met.Arguments[1], null); return(Query.EQ(field, value)); } // Any (Enumerable): x.Customer.Any(z => z.Name.StartsWith("John")) else if (method == "Any" && type == typeof(Enumerable) && paramType == ExpressionType.Parameter) { var field = this.GetField(met.Arguments[0]); var lambda = met.Arguments[1] as LambdaExpression; return(this.VisitExpression(lambda.Body, field + ".")); } // System.Linq.Enumerable methods (constant list items) else if (type == typeof(Enumerable)) { return(ParseEnumerableExpression(met)); } } throw new NotImplementedException("Not implemented Linq expression"); }
private Query VisitExpression(Expression expr) { if (expr.NodeType == ExpressionType.Equal) // == { var bin = expr as BinaryExpression; return(new QueryEquals(this.VisitMember(bin.Left), this.VisitValue(bin.Right))); } else if (expr is MemberExpression && expr.Type == typeof(bool)) // x.Active { return(Query.EQ(this.VisitMember(expr), new BsonValue(true))); } else if (expr.NodeType == ExpressionType.NotEqual) // != { var bin = expr as BinaryExpression; return(Query.Not(this.VisitMember(bin.Left), this.VisitValue(bin.Right))); } else if (expr.NodeType == ExpressionType.Not) // !x.Active { var bin = expr as UnaryExpression; return(Query.EQ(this.VisitMember(bin), new BsonValue(false))); } else if (expr.NodeType == ExpressionType.LessThan) // < { var bin = expr as BinaryExpression; return(Query.LT(this.VisitMember(bin.Left), this.VisitValue(bin.Right))); } else if (expr.NodeType == ExpressionType.LessThanOrEqual) // <= { var bin = expr as BinaryExpression; return(Query.LTE(this.VisitMember(bin.Left), this.VisitValue(bin.Right))); } else if (expr.NodeType == ExpressionType.GreaterThan) // > { var bin = expr as BinaryExpression; return(Query.GT(this.VisitMember(bin.Left), this.VisitValue(bin.Right))); } else if (expr.NodeType == ExpressionType.GreaterThanOrEqual) // >= { var bin = expr as BinaryExpression; return(Query.GTE(this.VisitMember(bin.Left), this.VisitValue(bin.Right))); } else if (expr is MethodCallExpression) { var met = expr as MethodCallExpression; var method = met.Method.Name; // StartsWith if (method == "StartsWith") { var value = this.VisitValue(met.Arguments[0]); return(Query.StartsWith(this.VisitMember(met.Object), value)); } // Contains else if (method == "Contains") { var value = this.VisitValue(met.Arguments[0]); return(Query.Contains(this.VisitMember(met.Object), value)); } // Equals else if (method == "Equals") { var value = this.VisitValue(met.Arguments[0]); return(Query.EQ(this.VisitMember(met.Object), value)); } } else if (expr is BinaryExpression && expr.NodeType == ExpressionType.AndAlso) { // AND var bin = expr as BinaryExpression; var left = this.VisitExpression(bin.Left); var right = this.VisitExpression(bin.Right); return(Query.And(left, right)); } else if (expr is BinaryExpression && expr.NodeType == ExpressionType.OrElse) { // OR var bin = expr as BinaryExpression; var left = this.VisitExpression(bin.Left); var right = this.VisitExpression(bin.Right); return(Query.Or(left, right)); } throw new NotImplementedException("Not implemented Linq expression"); }
private QueryBuilder convertQuery(string _field, string _operator, string _value) { _operator = _operator.ToLower(); bool _ok = false; Query _query = null; string _msg = string.Empty; switch (_operator) { case "all": //int order = Ascending) //_query = Query.All(); break; case "all_field": //string field, int order = Ascending) //_query = Query.All(); break; case "eq": //string field, BsonValue value) if (_value.IsNumeric()) { if (_value.IndexOf('.') != -1) { double _d = 0; if (double.TryParse(_value, out _d)) { _ok = true; _query = Query.EQ(_field, new BsonValue(_d)); } } else { int _val = 0; if (int.TryParse(_value, out _val)) { _ok = true; _query = Query.EQ(_field, new BsonValue(_val)); } } } else { _ok = true; _query = Query.EQ(_field, new BsonValue(_value)); } break; case "lt": //string field, BsonValue value) _value = _value.Trim(); if (_value.IsNumeric()) { _ok = true; _query = Query.LT(_field, new BsonValue(_value)); } else { _msg = "The field [" + _field + "] using operator [" + _operator + "] to compare value be not number: [" + _value + "]"; } break; case "lte": //string field, BsonValue value) _value = _value.Trim(); if (_value.IsNumeric()) { _ok = true; _query = Query.LTE(_field, new BsonValue(_value)); } else { _msg = "The field [" + _field + "] using operator [" + _operator + "] to compare value be not number: [" + _value + "]"; } break; case "gt": //string field, BsonValue value) _value = _value.Trim(); if (_value.IsNumeric()) { _ok = true; _query = Query.GT(_field, new BsonValue(_value)); } else { _msg = "The field [" + _field + "] using operator [" + _operator + "] to compare value be not number: [" + _value + "]"; } break; case "gte": //string field, BsonValue value) _value = _value.Trim(); if (_value.IsNumeric()) { _ok = true; _query = Query.GTE(_field, new BsonValue(_value)); } else { _msg = "The field [" + _field + "] using operator [" + _operator + "] to compare value be not number: [" + _value + "]"; } break; case "between": //string field, BsonValue start, BsonValue end, bool startEquals = true, bool endEquals = true) string[] a = _value.Split('|'); if (a.Length == 2) { string v1 = a[0].Trim(), v2 = a[1].Trim(); if (v1.IsNumeric() && v2.IsNumeric()) { _ok = true; _query = Query.Between(_field, new BsonValue(v1), new BsonValue(v2)); } else { _msg = "The field [" + _field + "] using operator [" + _operator + "] to compare value be not number: [" + _value + "]"; } } else { _msg = "The field [" + _field + "] using operator [" + _operator + "] to compare value be not format: [ number_start | number_end ]"; } break; case "start_with": //string field, string value) _ok = true; _query = Query.StartsWith(_field, _value); break; case "contains": //string field, string value) _ok = true; _query = Query.Contains(_field, _value); break; case "not": //string field, BsonValue value) _ok = true; _query = Query.Not(_field, new BsonValue(_value)); break; //case "not_query": //Query query, int order = Query.Ascending) // _query = Query.All(); // break; //case "in_bson_array": //string field, BsonArray value) // _query = Query.All(); // break; case "in_array": //string field, params BsonValue[] values) _value = _value.Trim(); if (string.IsNullOrEmpty(_value)) { _msg = "The field [" + _field + "] using operator [" + _operator + "] to compare value be not format: [ number_start | number_end ]"; } else { _ok = true; BsonValue[] a_in_array = _value.Split('|').Select(x => new BsonValue(x)).ToArray(); _query = Query.In(_field, a_in_array); } break; //case "in_ienumerable": //string field, IEnumerable<BsonValue> values) // _query = Query.All(); // break; } return(new QueryBuilder() { Ok = _ok, Query = _query, Msg = _msg }); }