public virtual S VisitQueryExpression(QueryExpression queryExpression, T data) { return(VisitChildren(queryExpression, data)); }
QueryExpression DecompileQuery(InvocationExpression invocation) { if (invocation == null) { return(null); } if (!(invocation.Target is MemberReferenceExpression mre)) { return(null); } switch (mre.MemberName) { case "Select": { if (invocation.Arguments.Count != 1) { return(null); } string parameterName; Expression body; if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body)) { QueryExpression query = new QueryExpression(); query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = ExtractQuery(mre) }); query.Clauses.Add(new QuerySelectClause { Expression = body.Detach() }); return(query); } return(null); } case "Cast": { if (invocation.Arguments.Count == 0 && mre.TypeArguments.Count == 1) { var typeArgument = mre.TypeArguments.First(); QueryExpression query = new QueryExpression(); string varName = GenerateVariableName(); query.Clauses.Add(new QueryFromClause { Identifier = varName, Expression = ExtractQuery(mre), Type = typeArgument.Detach() }); return(query); } return(null); } case "GroupBy": { if (invocation.Arguments.Count == 2) { string parameterName1, parameterName2; Expression keySelector, elementSelector; if (MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName1, out keySelector) && MatchSimpleLambda(invocation.Arguments.ElementAt(1), out parameterName2, out elementSelector) && parameterName1 == parameterName2) { QueryExpression query = new QueryExpression(); query.Clauses.Add(new QueryFromClause { Identifier = parameterName1, Expression = ExtractQuery(mre) }); query.Clauses.Add(new QueryGroupClause { Projection = elementSelector.Detach(), Key = keySelector.Detach() }); return(query); } } else if (invocation.Arguments.Count == 1) { string parameterName; Expression keySelector; if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out keySelector)) { QueryExpression query = new QueryExpression(); query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = ExtractQuery(mre) }); query.Clauses.Add(new QueryGroupClause { Projection = new IdentifierExpression(parameterName), Key = keySelector.Detach() }); return(query); } } return(null); } case "SelectMany": { if (invocation.Arguments.Count != 2) { return(null); } string parameterName; Expression collectionSelector; if (!MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName, out collectionSelector)) { return(null); } if (invocation.Arguments.ElementAt(1) is LambdaExpression lambda && lambda.Parameters.Count == 2 && lambda.Body is Expression) { ParameterDeclaration p1 = lambda.Parameters.ElementAt(0); ParameterDeclaration p2 = lambda.Parameters.ElementAt(1); QueryExpression query = new QueryExpression(); query.Clauses.Add(new QueryFromClause { Identifier = p1.Name, Expression = ExtractQuery(mre) }); query.Clauses.Add(new QueryFromClause { Identifier = p2.Name, Expression = collectionSelector.Detach() }); query.Clauses.Add(new QuerySelectClause { Expression = ((Expression)lambda.Body).Detach() }); return(query); } return(null); } case "Where": { if (invocation.Arguments.Count != 1) { return(null); } string parameterName; Expression body; if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body)) { QueryExpression query = new QueryExpression(); query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = ExtractQuery(mre) }); query.Clauses.Add(new QueryWhereClause { Condition = body.Detach() }); return(query); } return(null); } case "OrderBy": case "OrderByDescending": case "ThenBy": case "ThenByDescending": { if (invocation.Arguments.Count != 1) { return(null); } string parameterName; Expression orderExpression; if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out orderExpression)) { if (ValidateThenByChain(invocation, parameterName)) { QueryOrderClause orderClause = new QueryOrderClause(); InvocationExpression tmp = invocation; while (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending") { // insert new ordering at beginning orderClause.Orderings.InsertAfter( null, new QueryOrdering { Expression = orderExpression.Detach(), Direction = (mre.MemberName == "ThenBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending) }); tmp = (InvocationExpression)mre.Target; mre = (MemberReferenceExpression)tmp.Target; MatchSimpleLambda(tmp.Arguments.Single(), out parameterName, out orderExpression); } // insert new ordering at beginning orderClause.Orderings.InsertAfter( null, new QueryOrdering { Expression = orderExpression.Detach(), Direction = (mre.MemberName == "OrderBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending) }); QueryExpression query = new QueryExpression(); query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = ExtractQuery(mre) }); query.Clauses.Add(orderClause); return(query); } } return(null); } case "Join": case "GroupJoin": { if (invocation.Arguments.Count != 4) { return(null); } Expression source1 = mre.Target; Expression source2 = invocation.Arguments.ElementAt(0); string elementName1, elementName2; Expression key1, key2; if (!MatchSimpleLambda(invocation.Arguments.ElementAt(1), out elementName1, out key1)) { return(null); } if (!MatchSimpleLambda(invocation.Arguments.ElementAt(2), out elementName2, out key2)) { return(null); } if (invocation.Arguments.ElementAt(3) is LambdaExpression lambda && lambda.Parameters.Count == 2 && lambda.Body is Expression) { ParameterDeclaration p1 = lambda.Parameters.ElementAt(0); ParameterDeclaration p2 = lambda.Parameters.ElementAt(1); QueryExpression query = new QueryExpression(); query.Clauses.Add(new QueryFromClause { Identifier = elementName1, Expression = source1.Detach() }); QueryJoinClause joinClause = new QueryJoinClause(); joinClause.JoinIdentifier = elementName2; // join elementName2 joinClause.InExpression = source2.Detach(); // in source2 Match castMatch = castPattern.Match(source2); if (castMatch.Success) { Expression target = castMatch.Get <Expression>("inExpr").Single().Detach(); joinClause.Type = castMatch.Get <AstType>("targetType").Single().Detach(); joinClause.InExpression = target; } joinClause.OnExpression = key1.Detach(); // on key1 joinClause.EqualsExpression = key2.Detach(); // equals key2 if (mre.MemberName == "GroupJoin") { joinClause.IntoIdentifier = p2.Name; // into p2.Name } query.Clauses.Add(joinClause); Expression resultExpr = ((Expression)lambda.Body).Detach(); if (p1.Name != elementName1) { foreach (var identifier in resultExpr.Descendants.OfType <Identifier>().Where(id => id.Name == p1.Name)) { identifier.Name = elementName1; } } if (p2.Name != elementName2 && mre.MemberName != "GroupJoin") { foreach (var identifier in resultExpr.Descendants.OfType <Identifier>().Where(id => id.Name == p2.Name)) { identifier.Name = elementName2; } } query.Clauses.Add(new QuerySelectClause { Expression = resultExpr }); return(query); } return(null); } default: return(null); } }
public virtual S VisitQueryExpression(QueryExpression queryExpression, T data) { throw new NotImplementedException(); }