示例#1
0
 /// <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.");
 }