private void ParseNode <TKey, TAggregateRoot>(ParseTreeNode node, ref SortSpecification <TKey, TAggregateRoot> sortSpecification)
            where TKey : IEquatable <TKey>
            where TAggregateRoot : class, IAggregateRoot <TKey>
        {
            switch (node.Term.Name)
            {
            case "sort-specification":
                var suggestedPropertyName = node.ChildNodes[0].ChildNodes[0].Token.ValueString;
                var suggestedSortingOrder = node.ChildNodes[1].ChildNodes[0].Token.ValueString;
                var propertyName          = ParsingUtils.InferProperty <TAggregateRoot>(suggestedPropertyName)?.Name;
                if (string.IsNullOrEmpty(propertyName))
                {
                    throw new ParsingException("Expression parsed failed.", new[] { $"The property that has the name similar to {suggestedPropertyName} does not exist." });
                }

                var sortOrder = suggestedSortingOrder.ToUpper() == "A" ? SortOrder.Ascending : SortOrder.Descending;
                sortSpecification.Add(propertyName, sortOrder);
                break;

            case "concatenated-sort-specification":
                var leftNode  = node.ChildNodes[0];
                var rightNode = node.ChildNodes[2];
                ParseNode(leftNode, ref sortSpecification);
                ParseNode(rightNode, ref sortSpecification);
                break;
            }
        }
Beispiel #2
0
        private Expression ParseExpression <T>(ParseTreeNode node, ParameterExpression parameterExpression)
        {
            switch (node.Term.Name)
            {
            case "logical-operation":
                var leftLogicalOperandNode = node.ChildNodes[0];
                var logicalOperatorNode    = node.ChildNodes[1];
                var rightLogicalOprandNode = node.ChildNodes[2];
                switch (logicalOperatorNode.ChildNodes[0].Term.Name)
                {
                case "AND":
                    return(Expression.AndAlso(ParseExpression <T>(leftLogicalOperandNode, parameterExpression), ParseExpression <T>(rightLogicalOprandNode, parameterExpression)));

                case "OR":
                    return(Expression.OrElse(ParseExpression <T>(leftLogicalOperandNode, parameterExpression), ParseExpression <T>(rightLogicalOprandNode, parameterExpression)));
                }
                break;

            case "relational-operation":
                var leftRelationalOperandNode  = node.ChildNodes[0];
                var relationalOperatorNode     = node.ChildNodes[1];
                var rightRelationalOperandNode = node.ChildNodes[2];

                var leftExpression  = ParseExpression <T>(leftRelationalOperandNode, parameterExpression);
                var rightExpression = ParseExpression <T>(rightRelationalOperandNode, parameterExpression);

                if (leftExpression.NodeType == ExpressionType.Constant || rightExpression.NodeType == ExpressionType.Constant)
                {
                    FixExpressionType(ref leftExpression, ref rightExpression);
                }

                switch (relationalOperatorNode.ChildNodes[0].Term.Name)
                {
                case "EQ":
                    return(Expression.Equal(leftExpression, rightExpression));

                case "NE":
                    return(Expression.NotEqual(leftExpression, rightExpression));

                case "GE":
                    return(Expression.GreaterThanOrEqual(leftExpression, rightExpression));

                case "GT":
                    return(Expression.GreaterThan(leftExpression, rightExpression));

                case "LE":
                    return(Expression.LessThanOrEqual(leftExpression, rightExpression));

                case "LT":
                    return(Expression.LessThan(leftExpression, rightExpression));
                }
                break;

            case "not-operation":
                return(Expression.Not(ParseExpression <T>(node.ChildNodes[1], parameterExpression)));

            case "string-operation":
                var leftStringFunctionOperandNode  = node.ChildNodes[0];
                var stringFunctionNode             = node.ChildNodes[1];
                var rightStringFunctionOperandNode = node.ChildNodes[2];

                var leftStringFunctionExpression  = ParseExpression <T>(leftStringFunctionOperandNode, parameterExpression);
                var rightStringFunctionExpression = ParseExpression <T>(rightStringFunctionOperandNode, parameterExpression);
                switch (stringFunctionNode.ChildNodes[0].Term.Name)
                {
                case "SW":
                    return(Expression.Call(leftStringFunctionExpression, typeof(string).GetMethod("StartsWith", new[] { typeof(string) }), rightStringFunctionExpression));

                case "EW":
                    return(Expression.Call(leftStringFunctionExpression, typeof(string).GetMethod("EndsWith", new[] { typeof(string) }), rightStringFunctionExpression));

                case "CT":
                    return(Expression.Call(leftStringFunctionExpression, typeof(string).GetMethod("Contains"), rightStringFunctionExpression));
                }
                break;

            case "property":
                var inferredProperty = ParsingUtils.InferProperty <T>(node.ChildNodes[0].Token.ValueString);
                if (inferredProperty == null)
                {
                    throw new ParsingException("Expression parsed failed.", new[] { $"The property that has the name similar to {node.ChildNodes[0].Token.ValueString} does not exist." });
                }

                var propertyName = ParsingUtils.InferProperty <T>(node.ChildNodes[0].Token.ValueString).Name;
                return(Expression.Property(parameterExpression, node.ChildNodes[0].Token.ValueString));

            case "string":
                return(Expression.Constant(node.Token.Value));

            case "number":
                var expr = Expression.Constant(node.Token.Value);
                return(expr);
            }
            return(null);
        }