Exemple #1
0
        bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, out string transparentIdentifier)
        {
            transparentIdentifier = fromClause.Identifier;

            Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());

            if (!match.Success)
            {
                return(false);
            }
            QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
            Expression        nae1         = match.Get <Expression>("nae1").SingleOrDefault();
            string            nae1Name     = ExtractExpressionName(ref nae1);

            if (nae1Name == null)
            {
                return(false);
            }

            Expression nae2     = match.Get <Expression>("nae2").SingleOrDefault();
            string     nae2Name = ExtractExpressionName(ref nae2);

            if (nae1Name == null)
            {
                return(false);
            }

            // from * in (from x in ... select new { x = x, y = expr }) ...
            // =>
            // from x in ... let y = expr ...
            fromClause.Remove();
            selectClause.Remove();
            // Move clauses from innerQuery to query
            QueryClause insertionPos = null;

            foreach (var clause in innerQuery.Clauses)
            {
                query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
            }
            query.Clauses.InsertAfter(insertionPos, new QueryLetClause {
                Identifier = nae2Name, Expression = nae2.Detach()
            });
            return(true);
        }
        private bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, string continuationIdentifier, out string transparentIdentifier)
        {
            transparentIdentifier = fromClause.Identifier;

            Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());

            if (!match.Success)
            {
                return(false);
            }
            QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
            Expression        nae1         = match.Get <Expression>("nae1").SingleOrDefault();
            string            nae1Name     = ExtractExpressionName(ref nae1);

            if (nae1Name == null)
            {
                return(false);
            }

            Expression nae2     = match.Get <Expression>("nae2").SingleOrDefault();
            string     nae2Name = ExtractExpressionName(ref nae2);

            if (nae1Name == null)
            {
                return(false);
            }

            bool introduceLetClause = true;
            var  nae1Identifier     = nae1 as IdentifierExpression;
            var  nae2Identifier     = nae2 as IdentifierExpression;

            if (nae1Identifier != null && nae2Identifier != null && nae1Identifier.Identifier == nae1Name && nae2Identifier.Identifier == nae2Name)
            {
                introduceLetClause = false;
            }

            if (nae1Name != continuationIdentifier)
            {
                if (nae2Name == continuationIdentifier)
                {
                    //Members are in reversed order
                    string     tempName = nae1Name;
                    Expression tempNae  = nae1;

                    nae1Name = nae2Name;
                    nae1     = nae2;
                    nae2Name = tempName;
                    nae2     = tempNae;
                }
                else
                {
                    return(false);
                }
            }

            if (introduceLetClause && innerQuery.Clauses.OfType <QueryFromClause>().Any(from => from.Identifier == nae2Name))
            {
                return(false);
            }
            if (introduceLetClause && innerQuery.Clauses.OfType <QueryJoinClause>().Any(join => join.JoinIdentifier == nae2Name))
            {
                return(false);
            }

            // from * in (from x in ... select new { x = x, y = expr }) ...
            // =>
            // from x in ... let y = expr ...
            fromClause.Remove();
            selectClause.Remove();
            // Move clauses from innerQuery to query
            QueryClause insertionPos = null;

            foreach (var clause in innerQuery.Clauses)
            {
                query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
            }
            if (introduceLetClause)
            {
                query.Clauses.InsertAfter(insertionPos, new QueryLetClause {
                    Identifier = nae2Name, Expression = nae2.Detach()
                });
            }
            return(true);
        }
Exemple #3
0
        QueryExpression DecompileQuery(InvocationExpression invocation)
        {
            if (invocation == null)
            {
                return(null);
            }
            MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;

            if (mre == null)
            {
                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);
                }
                LambdaExpression lambda = invocation.Arguments.ElementAt(1) as LambdaExpression;
                if (lambda != null && 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);
                }
                LambdaExpression lambda = invocation.Arguments.ElementAt(3) as LambdaExpression;
                if (lambda != null && 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);
            }
        }