/// <summary> /// Visits the children of the <see cref="T:System.Linq.Expressions.MethodCallExpression"/>. /// </summary> /// <param name="node">The expression to visit.</param> /// <returns> /// The modified expression, if it or any subexpression was modified; otherwise, returns the /// original expression. /// </returns> /// <exception cref="NotSupportedException"></exception> protected override Expression?VisitMethodCall(MethodCallExpression node) { if (node is null) { return(node); } if (node.Method.DeclaringType == typeof(Queryable)) { if (node.Method.Name == "Where") { node = (MethodCallExpression)Evaluator.PartialEval(node); Visit(node.Arguments[0]); var lambda = (LambdaExpression)StripQuotes(node.Arguments[1]); var CurrentClause = new WhereVisitor <TObject>(Count).WhereProjection(lambda.Body); ++Count; foreach (var Source in Builders.Keys) { Builders[Source].WhereClause.Combine(CurrentClause.Copy()); } return(node); } if (node.Method.Name == "Select") { Visit(node.Arguments[0]); var lambda = (LambdaExpression)StripQuotes(node.Arguments[1]); var Columns = new ColumnProjector().ProjectColumns(lambda.Body); foreach (var Source in Builders.Keys) { var ParentMappings = Source.GetChildMappings(typeof(TObject)) .SelectMany(x => Source.GetParentMapping(x.ObjectType)) .Distinct(); foreach (var Column in Columns) { if (ParentMappings.Any(x => x.ContainsProperty(Column.Name))) { Builders[Source].SelectValues.Add(Column); } } } return(node); } if (node.Method.Name == "ThenBy" || node.Method.Name == "OrderBy" || node.Method.Name == "OrderByDescending" || node.Method.Name == "ThenByDescending") { Visit(node.Arguments[0]); var lambda = (LambdaExpression)StripQuotes(node.Arguments[1]); var Columns = new ColumnProjector().ProjectColumns(lambda.Body); foreach (var Source in Builders.Keys) { var ParentMappings = Source.GetChildMappings(typeof(TObject)) .SelectMany(x => Source.GetParentMapping(x.ObjectType)) .Distinct(); foreach (var Column in Columns) { if (ParentMappings.Any(x => x.ContainsProperty(Column.Name))) { Builders[Source].OrderByValues.Add(new OrderByClause(Builders[Source].OrderByValues.Count, Column, node.Method.Name.Contains("Descending", StringComparison.OrdinalIgnoreCase) ? Direction.Descending : Direction.Ascending)); } } } return(node); } if (node.Method.Name == "Distinct") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Distinct = true; } return(node); } if (node.Method.Name == "First" || node.Method.Name == "FirstOrDefault" || node.Method.Name == "Single" || node.Method.Name == "SingleOrDefault") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Top = 1; } return(node); } if (node.Method.Name == "Take") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Top = (int)((node.Arguments[1] as ConstantExpression)?.Value ?? 1); } return(node); } if (node.Method.Name == "Skip") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Skip = (int)((node.Arguments[1] as ConstantExpression)?.Value ?? 1); } return(node); } if (node.Method.Name == "Count") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Count = true; } return(node); } } throw new NotSupportedException($"The method '{node.Method.Name}' is not supported."); }