private void VisitMethodCall(ParameterExpression[] parameters, MethodCallExpression expression, QueryContainer container) { var declaringType = expression.Method.DeclaringType; var enumerableType = (declaringType.GetInterfaces() .Where(x => x.IsGenericType) .Where(x => x.GetGenericTypeDefinition() == typeof(IEnumerable<>)) .Select(x => x.GetGenericArguments()[0]) .FirstOrDefault() != null); if (enumerableType && expression.Method.Name == "Contains") { var memberExpression = expression.Object as MemberExpression; if (memberExpression != null) { var constantExpression = memberExpression.Expression as ConstantExpression; var prop = memberExpression.Member; var fieldName = prop.Name; if (constantExpression != null) { var value = constantExpression.Value; var fieldType = value.GetType(); var fieldInfo = fieldType.GetField(fieldName); var field = fieldInfo.GetValue(value); var bsonValue = BsonArray.Create(field); var inverted = container.Query.Inverted; container.Query = new InRepositoryQuery { Value = bsonValue, Inverted = inverted }; } } Visit(parameters, expression.Arguments[0], container); } else if ((declaringType == typeof(IEnumerable) || declaringType == typeof(Enumerable) && declaringType != typeof(string) && declaringType.IsPrimitive == false) && expression.Method.Name == "Contains") { var inverted = container.Query.Inverted; var memberExpression = expression.Arguments[0] as MemberExpression; if (memberExpression != null && memberExpression.Expression is ParameterExpression) { container.Query.Operand = MongoOperand.Equals; } else { container.Query = new InRepositoryQuery { Inverted = inverted }; } Visit(parameters, expression.Arguments[0], container); Visit(parameters, expression.Arguments[1], container); } else if (expression.Method.Name == "get_Item" && expression.Object != null && expression.Object.Type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { Visit(parameters, expression.Object, container); var dictionaryKey = GetValueFromExpression(expression.Arguments[0]) as string; container.Query.PropertyName += "." + dictionaryKey; //Append the dictionary key } else if(expression.Method.Name == "IsNullOrEmpty") { var orRepositoryQuery = new OrRepositoryQuery { LeftContainer = new QueryContainer(new RepositoryQuery()) { Query = { Value = "", Operand = MongoOperand.Equals, Inverted = container.Query.Inverted } } }; Visit(null, expression.Arguments[0], orRepositoryQuery.LeftContainer); orRepositoryQuery.RightContainer = new QueryContainer(new RepositoryQuery()) { Query = { Value = null, Operand = MongoOperand.Equals, Inverted = container.Query.Inverted } }; Visit(null, expression.Arguments[0], orRepositoryQuery.RightContainer); container.Query = orRepositoryQuery; } else if(expression.Method.Name == "IsNotNullOrEmpty") { var orRepositoryQuery = new OrRepositoryQuery { LeftContainer = new QueryContainer(new RepositoryQuery()) { Query = { Value = "", Operand = MongoOperand.NotEquals } } }; Visit(null, expression.Arguments[0], orRepositoryQuery.LeftContainer); orRepositoryQuery.RightContainer = new QueryContainer(new RepositoryQuery()) { Query = { Value = null, Operand = MongoOperand.NotEquals } }; Visit(null, expression.Arguments[0], orRepositoryQuery.RightContainer); container.Query = orRepositoryQuery; } else if (expression.Method.Name == "Parse") { var memberExpression = expression.Arguments[0] as MemberExpression; if (expression.Arguments[0] is ConstantExpression || (memberExpression != null && memberExpression.Expression is ConstantExpression)) { var value = GetValueFromExpression(expression); container.Query.Value = BsonValue.Create(value); } else { throw new NotSupportedException("Parse on non-Constant Expressions is not supported"); } } else if (expression.Method.Name == "ToString") { var memberExpression = expression.Object as MemberExpression; if (expression.Object is ConstantExpression || (memberExpression != null && memberExpression.Expression is ConstantExpression)) { var value = GetValueFromExpression(expression); container.Query.Value = BsonValue.Create(value); } else { throw new NotSupportedException("ToString on non-Constant Expressions is not supported"); } } else { throw new NotSupportedException(string.Format("Method {0} is not supported", expression.Method.Name)); } }
private void VisitBinary(ParameterExpression[] parameters, BinaryExpression binaryExpression, QueryContainer container) { QueryContainer queryLeft; QueryContainer queryRight; switch (binaryExpression.NodeType) { case ExpressionType.AndAlso: case ExpressionType.And: var andQuery = new AndRepositoryQuery(); queryLeft = new QueryContainer(new RepositoryQuery()); queryRight = new QueryContainer(new RepositoryQuery()); andQuery.LeftContainer = queryLeft; andQuery.RightContainer = queryRight; container.Query = andQuery; break; case ExpressionType.Or: case ExpressionType.OrElse: var orQuery = new OrRepositoryQuery(); queryLeft = new QueryContainer(new RepositoryQuery()); queryRight = new QueryContainer(new RepositoryQuery()); orQuery.LeftContainer = queryLeft; orQuery.RightContainer = queryRight; container.Query = orQuery; break; default: container.Query.Operand = FindMongoOperand(binaryExpression.NodeType); queryLeft = queryRight = container; break; } Visit(parameters, binaryExpression.Left, queryLeft); Visit(parameters, binaryExpression.Right, queryRight); }