/// <inheritdoc /> protected override Expression VisitMethodCall(MethodCallExpression expression) { LogWriter.WriteLine($"VisitMethodCall: {expression}, method {expression.Method.Name}, args: {string.Join(", ",expression.Arguments.Select(a => a.ToString()))}"); var method = expression.Method; switch (method.Name) { case "Contains": case "StartsWith": case "EndsWith": var obj = Evaluate(expression.Object); var pattern = Evaluate(expression.Arguments[0]); _state.SetColumn(obj.ToString()); _state.SetFunction(method.Name, pattern); return(expression); case "Min": case "Max": case "Count": case "Average": case "Sum": using (_state.PushCollectorMode(QueryCollectionState.Aggregate)) { object value = null; if (expression.Arguments.Count > 1) { throw new InvalidOperationException($"Unsupported number of aggregate function arguments: {expression.Arguments.Count}"); } if (expression.Arguments.Count > 0) { value = Evaluate(expression.Arguments[0]); } _state.SetFunction(method.Name, value); } return(expression); case "Column": var columnName = Evaluate(expression.Arguments[0]).ToString(); _arguments.Push(columnName); _state.SetColumn(columnName); return(expression); } return(base.VisitMethodCall(expression)); // throws }
/// <inheritdoc /> public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index) { LogWriter.WriteLine($"VisitResultOperator: {resultOperator}, type {resultOperator.GetType().Name}"); switch (resultOperator) { // First() case FirstResultOperator _: _collector.Take = 1; break; // Count() case CountResultOperator _: case LongCountResultOperator _: _collector.SetResultAggregationType(AggregationTypeStrict.Count); break; // Take() case TakeResultOperator takeOperator: var takeExpr = takeOperator.Count; if (takeExpr.NodeType == ExpressionType.Constant) { _collector.Take = (int)((ConstantExpression)takeExpr).Value; } else { throw new NotSupportedException("Currently not supporting methods or variables in the Skip or Take clause."); } break; // Skip() case SkipResultOperator skipOperator: var skipExpr = skipOperator.Count; if (skipExpr.NodeType == ExpressionType.Constant) { _collector.Skip = (int)((ConstantExpression)skipExpr).Value; } else { throw new NotSupportedException("Currently not supporting methods or variables in the Skip or Take clause."); } break; // Min() case MinResultOperator _: _state.SetFunction("Min", null); break; // Max() case MaxResultOperator _: _state.SetFunction("Max", null); break; // Average() case AverageResultOperator _: _state.SetFunction("Average", null); break; // GroupBy() case GroupResultOperator groupOperator: using (_state.PushCollectorMode(QueryCollectionState.GroupBy)) { var key = groupOperator.KeySelector; var elementSelector = groupOperator.ElementSelector; UpdateEntitySchemaQueryExpression(key); UpdateEntitySchemaQueryExpression(elementSelector); if (key is NewExpression newKeySelector) { int position = 0; foreach (var memberInfo in newKeySelector.Members) { _state.SetColumnAlias(position++, memberInfo.Name); } } } break; } }