public static Expression CreateFilterExpression(Type type, InvocationQuerySyntaxNode node)
        {
            var visitor    = new ExpressionFilterQuerySyntaxVisitor(type);
            var filterBody = visitor.Visit(node);

            return(Expression.Lambda(filterBody, visitor.Parameter));
        }
        // KnownFunctions

        private static Expression NotInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // not(condition) --> !condition
            var condition = visitor.Visit(node.Arguments[0]);

            return(Expression.Not(condition));
        }
        private static Expression LteInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // lte(property, value) --> i.property <= value
            var property = visitor.Visit(node.Arguments[0]);
            var value    = visitor.Visit(node.Arguments[1]);

            return(QuerySyntaxHelper.Compare(property, value, Expression.LessThanOrEqual));
        }
        private static Expression GtInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // gt(property, value) --> i.property > value
            var property = visitor.Visit(node.Arguments[0]);
            var value    = visitor.Visit(node.Arguments[1]);

            return(QuerySyntaxHelper.Compare(property, value, Expression.GreaterThan));
        }
        private static Expression InInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // in(property, value1, value2, value3, ...) --> Enumerable.Contains(new[] { value1, value2, value3, ... }, i.property)
            var property = visitor.Visit(node.Arguments[0]);
            var values   = QuerySyntaxHelper.NewArray(property.Type, node.Arguments.Skip(1).Select(visitor.Visit));

            return(QuerySyntaxHelper.InvokeContains(property.Type, values, property));
        }
        private static Expression DateInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // date('value') --> DateTime.Parse('value')
            var dateTimeString = node.Arguments[0].AsStringLiteral();
            var dateTime       = DateTime.Parse(dateTimeString);

            return(Expression.Constant(dateTime));
        }
        private static Expression CreateSizeFilterForArrayProperty(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node, Func <Expression, Expression, Expression> filter)
        {
            // filter(arrayProperty, value) --> filter(Enumerable.Count(i.arrayProperty), value)
            var arrayProperty = visitor.Visit(node.Arguments[0]);
            var value         = visitor.Visit(node.Arguments[1]);
            var itemType      = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type);

            return(QuerySyntaxHelper.Compare(QuerySyntaxHelper.InvokeCount(itemType, arrayProperty), value, filter));
        }
        private static Expression MatchInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // match(arrayProperty, filter) --> Enumerable.Any(i.arrayProperty, ii => filter(ii))
            var arrayProperty = visitor.Visit(node.Arguments[0]);
            var itemType      = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type);
            var itemFilter    = CreateFilterExpression(itemType, (InvocationQuerySyntaxNode)node.Arguments[1]);

            return(QuerySyntaxHelper.InvokeAny(itemType, arrayProperty, itemFilter));
        }
        private static Expression RegexInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // regex(property, pattern, 'option1', 'option2', 'option3', ...) --> Regex.IsMatch(i.property, pattern, option1 | option2 | option3 | ...)
            var property = visitor.Visit(node.Arguments[0]);
            var pattern  = visitor.Visit(node.Arguments[1]);
            var options  = Expression.Constant(node.Arguments.Skip(2).Aggregate(RegexOptions.None, (r, n) => r | n.AsEnumIdentifier <RegexOptions>()));

            return(QuerySyntaxHelper.InvokeRegex(property, pattern, options));
        }
        private static Expression CreateAnyFilterForArrayProperty(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node, Func <Expression, Expression, Expression> filter)
        {
            // filter(arrayProperty, item) --> Enumerable.Any(i.arrayProperty, ii => filter(ii, item))
            var arrayProperty = visitor.Visit(node.Arguments[0]);
            var item          = visitor.Visit(node.Arguments[1]);
            var itemType      = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type);
            var itemParameter = Expression.Parameter(itemType);

            return(QuerySyntaxHelper.InvokeAny(itemType, arrayProperty, Expression.Lambda(QuerySyntaxHelper.Compare(itemParameter, item, filter), itemParameter)));
        }
        private static Expression ExistsInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // exists(property, true) --> i.property != null
            // exists(property, false) --> i.property == null
            var property  = visitor.Visit(node.Arguments[0]);
            var exists    = (node.Arguments.Count < 2 || node.Arguments[1].AsBooleanLiteral());
            var nullValue = Expression.Constant(null);

            return(exists ? Expression.NotEqual(property, nullValue) : Expression.Equal(property, nullValue));
        }
        // Helpers

        private static Expression CreateFilterForArrayProperty(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node, Func <Type, Expression, Expression, Expression> filter)
        {
            // filter(arrayProperty, item1, item2, item3, ...) --> filter(new[] { item1, item2, item3, ... }, ii => Enumerable.Contains(i.arrayProperty, ii))
            var arrayProperty = visitor.Visit(node.Arguments[0]);
            var itemType      = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type);
            var items         = QuerySyntaxHelper.NewArray(itemType, node.Arguments.Skip(1).Select(visitor.Visit));
            var itemParameter = Expression.Parameter(itemType);
            var itemFilter    = QuerySyntaxHelper.InvokeContains(itemType, arrayProperty, itemParameter);

            return(filter(itemType, items, Expression.Lambda(itemFilter, itemParameter)));
        }
示例#13
0
        private Expression <Func <TDocument, bool> > BuildFilter(IHttpRequest request, string documentIdKey)
        {
            var filterMethod = ParseFilter(request, documentIdKey);

            if (filterMethod != null)
            {
                return((Expression <Func <TDocument, bool> >)ExpressionFilterQuerySyntaxVisitor.CreateFilterExpression(typeof(TDocument), filterMethod));
            }

            return(null);
        }
        private static Expression AndInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // and(condition1, condition2, condition3, ...) --> (((condition1 && condition2) && condition3) && ...)

            Expression result = null;

            var conditions = node.Arguments.Select(visitor.Visit);

            foreach (var condition in conditions)
            {
                result = (result != null)
                    ? Expression.AndAlso(result, condition)
                    : condition;
            }

            return(result);
        }
        private static Expression OrInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
        {
            // or(condition1, condition2, condition3, ...) --> (((condition1 || condition2) || condition3) || ...)

            Expression result = null;

            var conditions = node.Arguments.Select(visitor.Visit);

            foreach (var condition in conditions)
            {
                result = (result != null)
                    ? Expression.OrElse(result, condition)
                    : condition;
            }

            return(result);
        }
 private static Expression AnyNotEqInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // anyNotEq(arrayProperty, item) --> !Enumerable.Any(i.arrayProperty, ii => ii == item)
     return(Expression.Not(AnyEqInvocation(visitor, node)));
 }
 private static Expression AnyInInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // anyIn(arrayProperty, item1, item2, item3, ...) --> Enumerable.Any(new[] { item1, item2, item3, ... }, ii => Enumerable.Contains(i.arrayProperty, ii))
     return(CreateFilterForArrayProperty(visitor, node, QuerySyntaxHelper.InvokeAny));
 }
 private static Expression NotInInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // notIn(property, value1, value2, value3, ...) --> !Enumerable.Contains(new[] { value1, value2, value3, ... }, i.property)
     return(Expression.Not(InInvocation(visitor, node)));
 }
 private static Expression AnyNotInInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // anyNotIn(arrayProperty, item1, item2, item3, ...) --> !Enumerable.Any(new[] { item1, item2, item3, ... }, ii => Enumerable.Contains(i.arrayProperty, ii))
     return(Expression.Not(AnyInInvocation(visitor, node)));
 }
 private static Expression AnyGtInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // anyGt(arrayProperty, item) --> Enumerable.Any(i.arrayProperty, ii => ii > item)
     return(CreateAnyFilterForArrayProperty(visitor, node, Expression.GreaterThan));
 }
 private static Expression AnyLteInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // anyLte(arrayProperty, item) --> Enumerable.Any(i.arrayProperty, ii => ii <= item)
     return(CreateAnyFilterForArrayProperty(visitor, node, Expression.LessThanOrEqual));
 }
 private static Expression SizeGtInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // sizeGt(arrayProperty, value) --> Enumerable.Count(i.arrayProperty) > value
     return(CreateSizeFilterForArrayProperty(visitor, node, Expression.GreaterThan));
 }
 private static Expression SizeLteInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node)
 {
     // sizeLte(arrayProperty, value) --> Enumerable.Count(i.arrayProperty) <= value
     return(CreateSizeFilterForArrayProperty(visitor, node, Expression.LessThanOrEqual));
 }