Example #1
0
        private static Expression BuildOperatorExpression(Expression propertyExp, IFilterRule rule, BuildExpressionOptions options, Type type)
        {
            Expression expression;
            string     oper = rule.Operator.ToLower();

            switch (oper)
            {
            case "in":
                expression = In(type, rule.Value, propertyExp, options);
                break;

            case "not_in":
                expression = NotIn(type, rule.Value, propertyExp, options);
                break;

            case "equal":
                expression = Equals(type, rule.Value, propertyExp, options);
                break;

            case "not_equal":
                expression = NotEquals(type, rule.Value, propertyExp, options);
                break;

            case "between":
                expression = Between(type, rule.Value, propertyExp, options);
                break;

            case "not_between":
                expression = NotBetween(type, rule.Value, propertyExp, options);
                break;

            case "less":
                expression = LessThan(type, rule.Value, propertyExp, options);
                break;

            case "less_or_equal":
                expression = LessThanOrEqual(type, rule.Value, propertyExp, options);
                break;

            case "greater":
                expression = GreaterThan(type, rule.Value, propertyExp, options);
                break;

            case "greater_or_equal":
                expression = GreaterThanOrEqual(type, rule.Value, propertyExp, options);
                break;

            case "begins_with":
                expression = BeginsWith(type, rule.Value, propertyExp);
                break;

            case "not_begins_with":
                expression = NotBeginsWith(type, rule.Value, propertyExp);
                break;

            case "contains":
                expression = Contains(type, rule.Value, propertyExp);
                break;

            case "not_contains":
                expression = NotContains(type, rule.Value, propertyExp);
                break;

            case "ends_with":
                expression = EndsWith(type, rule.Value, propertyExp);
                break;

            case "not_ends_with":
                expression = NotEndsWith(type, rule.Value, propertyExp);
                break;

            case "is_empty":
                expression = IsEmpty(propertyExp);
                break;

            case "is_not_empty":
                expression = IsNotEmpty(propertyExp);
                break;

            case "is_null":
                expression = IsNull(propertyExp);
                break;

            case "is_not_null":
                expression = IsNotNull(propertyExp);
                break;

            default:
                //custom operators support
                var operators = options.Operators;
                if (operators != null && operators.Count() > 0)
                {
                    var customOperator = (from p in operators where p.Operator.ToLower() == oper select p).FirstOrDefault();
                    if (customOperator != null)
                    {
                        return(customOperator.GetExpression(type, rule, propertyExp, options));
                    }
                }

                throw new Exception($"Unknown expression operator: {rule.Operator}");
            }

            return(expression);
        }
Example #2
0
        /// <summary>
        /// Gets the filtered collection after applying the provided filter rules.
        /// </summary>
        /// <typeparam name="T">The generic type.</typeparam>
        /// <param name="queryable">The queryable.</param>
        /// <param name="filterRule">The filter rule.</param>
        /// <param name="useIndexedProperty">Whether or not to use indexed property</param>
        /// <param name="indexedPropertyName">The indexable property to use</param>
        /// <returns>Filtered IQueryable</returns>
        public static IQueryable <T> BuildQuery <T>(this IEnumerable <T> queryable, IFilterRule filterRule, bool useIndexedProperty = false, string indexedPropertyName = null)
        {
            string parsedQuery;

            return(BuildQuery(queryable.AsQueryable(), filterRule, out parsedQuery, useIndexedProperty, indexedPropertyName));
        }
Example #3
0
        private static Expression BuildExpressionTree(ParameterExpression pe, IFilterRule rule, BuildExpressionOptions options)
        {
            if (rule.Rules != null && rule.Rules.Any())
            {
                var expressions =
                    rule.Rules.Select(childRule => BuildExpressionTree(pe, childRule, options))
                    .Where(expression => expression != null)
                    .ToList();

                var expressionTree = expressions.First();

                var counter = 1;
                while (counter < expressions.Count)
                {
                    expressionTree = rule.Condition.ToLower() == "or"
                        ? Expression.Or(expressionTree, expressions[counter])
                        : Expression.And(expressionTree, expressions[counter]);
                    counter++;
                }

                return(expressionTree);
            }
            if (rule.Field != null)
            {
                Type type;

                switch (rule.Type)
                {
                case "integer":
                    type = typeof(int);
                    break;

                case "double":
                    type = typeof(double);
                    break;

                case "string":
                    type = typeof(string);
                    break;

                case "date":
                case "datetime":
                    type = typeof(DateTime);
                    break;

                case "boolean":
                    type = typeof(bool);
                    break;

                default:
                    throw new Exception($"Unexpected data type {rule.Type}");
                }

                if (options.UseIndexedProperty)
                {
                    var propertyExp = Expression.Property(pe, options.IndexedPropertyName, Expression.Constant(rule.Field));
                    return(BuildOperatorExpression(propertyExp, rule, options, type));
                }
                else
                {
                    var propertyList = rule.Field.Split('.');
                    if (propertyList.Length > 1)
                    {
                        var propertyCollectionEnumerator = propertyList.AsEnumerable().GetEnumerator();
                        return(BuildNestedExpression(pe, propertyCollectionEnumerator, rule, options, type));
                    }
                    else
                    {
                        var propertyExp = Expression.Property(pe, rule.Field);
                        return(BuildOperatorExpression(propertyExp, rule, options, type));
                    }
                }
            }
            return(null);
        }
Example #4
0
        private static Expression BuildNestedExpression(Expression expression, IEnumerator <string> propertyCollectionEnumerator, IFilterRule rule, BuildExpressionOptions options, Type type)
        {
            while (propertyCollectionEnumerator.MoveNext())
            {
                var propertyName = propertyCollectionEnumerator.Current;
                var property     = expression.Type.GetProperty(propertyName);
                expression = Expression.Property(expression, property);

                var propertyType = property.PropertyType;
                var enumerable   = propertyType.GetInterface("IEnumerable`1");
                if (propertyType != typeof(string) && enumerable != null)
                {
                    var elementType         = enumerable.GetGenericArguments()[0];
                    var predicateFnType     = typeof(Func <,>).MakeGenericType(elementType, typeof(bool));
                    var parameterExpression = Expression.Parameter(elementType);

                    Expression body      = BuildNestedExpression(parameterExpression, propertyCollectionEnumerator, rule, options, type);
                    var        predicate = Expression.Lambda(predicateFnType, body, parameterExpression);

                    var queryable = Expression.Call(typeof(Queryable), "AsQueryable", new[] { elementType }, expression);

                    return(Expression.Call(
                               typeof(Queryable),
                               "Any",
                               new[] { elementType },
                               queryable,
                               predicate
                               ));
                }
            }

            return(BuildOperatorExpression(expression, rule, options, type));
        }
Example #5
0
        /// <summary>
        /// Gets the filtered collection after applying the provided filter rules.
        /// Returns the string representation for diagnostic purposes.
        /// </summary>
        /// <typeparam name="T">The generic type.</typeparam>
        /// <param name="queryable">The queryable.</param>
        /// <param name="filterRule">The filter rule.</param>
        /// <param name="options">The options to use when building the expression</param>
        /// <returns>Filtered IQueryable.</returns>
        public static IQueryable <T> BuildQuery <T>(this IQueryable <T> queryable, IFilterRule filterRule, BuildExpressionOptions options)
        {
            string parsedQuery;

            return(BuildQuery(queryable, filterRule, options, out parsedQuery));
        }
Example #6
0
        /// <summary>
        /// Builds a predicate that returns whether an input test object passes the filter rule.
        /// </summary>
        /// <typeparam name="T">The generic type of the input object to test.</typeparam>
        /// <param name="filterRule">The filter rule.</param>
        /// <param name="options">The options to use when building the expression</param>
        /// <returns>A predicate function implementing the filter rule</returns>
        public static Func <T, bool> BuildPredicate <T>(this IFilterRule filterRule, BuildExpressionOptions options)
        {
            string parsedQuery;

            return(BuildPredicate <T>(filterRule, options, out parsedQuery));
        }
        private static Expression BuildExpressionTree(ParameterExpression pe, IFilterRule rule, BuildExpressionOptions options)
        {
            if (rule.Rules != null && rule.Rules.Any())
            {
                var expressions =
                    rule.Rules.Select(childRule => BuildExpressionTree(pe, childRule, options))
                    .Where(expression => expression != null)
                    .ToList();

                var expressionTree = expressions.First();

                var counter = 1;
                while (counter < expressions.Count)
                {
                    expressionTree = rule.Condition.ToLower() == "or"
                        ? Expression.Or(expressionTree, expressions[counter])
                        : Expression.And(expressionTree, expressions[counter]);
                    counter++;
                }

                return(expressionTree);
            }
            if (rule.Field != null)
            {
                Type type;

                switch (rule.Type)
                {
                case "integer":
                    type = typeof(int);
                    break;

                case "double":
                    type = typeof(double);
                    break;

                case "string":
                    type = typeof(string);
                    break;

                case "date":
                case "datetime":
                    type = typeof(DateTime);
                    break;

                case "boolean":
                    type = typeof(bool);
                    break;

                default:
                    throw new Exception($"Unexpected data type {rule.Type}");
                }

                Expression propertyExp = null;
                if (options.UseIndexedProperty)
                {
                    propertyExp = Expression.Property(pe, options.IndexedPropertyName, Expression.Constant(rule.Field));
                }
                else
                {
                    var propertyList = rule.Field.Split('.').ToList();
                    if (propertyList.Count() > 1)
                    {
                        propertyExp = Expression.Property(pe, propertyList.First());
                        foreach (var prop in propertyList.Skip(1))
                        {
                            propertyExp = Expression.Property(propertyExp, prop);
                        }
                    }
                    else
                    {
                        propertyExp = Expression.Property(pe, rule.Field);
                    }
                }

                Expression expression;

                switch (rule.Operator.ToLower())
                {
                case "in":
                    expression = In(type, rule.Value, propertyExp, options);
                    break;

                case "not_in":
                    expression = NotIn(type, rule.Value, propertyExp, options);
                    break;

                case "equal":
                    expression = Equals(type, rule.Value, propertyExp, options);
                    break;

                case "not_equal":
                    expression = NotEquals(type, rule.Value, propertyExp, options);
                    break;

                case "between":
                    expression = Between(type, rule.Value, propertyExp, options);
                    break;

                case "not_between":
                    expression = NotBetween(type, rule.Value, propertyExp, options);
                    break;

                case "less":
                    expression = LessThan(type, rule.Value, propertyExp, options);
                    break;

                case "less_or_equal":
                    expression = LessThanOrEqual(type, rule.Value, propertyExp, options);
                    break;

                case "greater":
                    expression = GreaterThan(type, rule.Value, propertyExp, options);
                    break;

                case "greater_or_equal":
                    expression = GreaterThanOrEqual(type, rule.Value, propertyExp, options);
                    break;

                case "begins_with":
                    expression = BeginsWith(type, rule.Value, propertyExp);
                    break;

                case "not_begins_with":
                    expression = NotBeginsWith(type, rule.Value, propertyExp);
                    break;

                case "contains":
                    expression = Contains(type, rule.Value, propertyExp);
                    break;

                case "not_contains":
                    expression = NotContains(type, rule.Value, propertyExp);
                    break;

                case "ends_with":
                    expression = EndsWith(type, rule.Value, propertyExp);
                    break;

                case "not_ends_with":
                    expression = NotEndsWith(type, rule.Value, propertyExp);
                    break;

                case "is_empty":
                    expression = IsEmpty(propertyExp);
                    break;

                case "is_not_empty":
                    expression = IsNotEmpty(propertyExp);
                    break;

                case "is_null":
                    expression = IsNull(propertyExp);
                    break;

                case "is_not_null":
                    expression = IsNotNull(propertyExp);
                    break;

                default:
                    throw new Exception($"Unknown expression operator: {rule.Operator}");
                }

                return(expression);
            }
            return(null);
        }
 /// <summary>
 /// Gets the filtered collection after applying the provided filter rules.
 /// Returns the string representation for diagnostic purposes.
 /// </summary>
 /// <typeparam name="T">The generic type.</typeparam>
 /// <param name="queryable">The queryable.</param>
 /// <param name="filterRule">The filter rule.</param>
 /// <param name="parsedQuery">The parsed query.</param>
 /// <param name="useIndexedProperty">Whether or not to use indexed property</param>
 /// <param name="indexedPropertyName">The indexable property to use</param>
 /// <returns>Filtered IQueryable.</returns>
 public static IQueryable <T> BuildQuery <T>(this IQueryable <T> queryable, IFilterRule filterRule, out string parsedQuery, bool useIndexedProperty = false, string indexedPropertyName = null)
 {
     return(BuildQuery(queryable, filterRule, new BuildExpressionOptions {
         UseIndexedProperty = useIndexedProperty, IndexedPropertyName = indexedPropertyName
     }, out parsedQuery));
 }
Example #9
0
        private IQueryable <TEntity> ApplyFilterRule <TEntity>(IQueryable <TEntity> queryable, IFilterRule filterRule)
        {
            var lambda = filterRule.GetExpression <TEntity>();

            MethodCallExpression result = Expression.Call(
                typeof(Queryable), "Where",
                new[]
            {
                queryable.ElementType
            },
                queryable.Expression,
                lambda);

            return(queryable.Provider.CreateQuery <TEntity>(result));
        }
Example #10
0
        private static Expression BuildOperatorExpression(Expression propertyExp, IFilterRule rule, BuildExpressionOptions options, Type type)
        {
            Expression expression;

            switch (rule.Operator.ToLower())
            {
            case "in":
                expression = In(type, rule.Value, propertyExp, options);
                break;

            case "not_in":
                expression = NotIn(type, rule.Value, propertyExp, options);
                break;

            case "equal":
                expression = Equals(type, rule.Value, propertyExp, options);
                break;

            case "not_equal":
                expression = NotEquals(type, rule.Value, propertyExp, options);
                break;

            case "between":
                expression = Between(type, rule.Value, propertyExp, options);
                break;

            case "not_between":
                expression = NotBetween(type, rule.Value, propertyExp, options);
                break;

            case "less":
                expression = LessThan(type, rule.Value, propertyExp, options);
                break;

            case "less_or_equal":
                expression = LessThanOrEqual(type, rule.Value, propertyExp, options);
                break;

            case "greater":
                expression = GreaterThan(type, rule.Value, propertyExp, options);
                break;

            case "greater_or_equal":
                expression = GreaterThanOrEqual(type, rule.Value, propertyExp, options);
                break;

            case "begins_with":
                expression = BeginsWith(type, rule.Value, propertyExp);
                break;

            case "not_begins_with":
                expression = NotBeginsWith(type, rule.Value, propertyExp);
                break;

            case "contains":
                expression = Contains(type, rule.Value, propertyExp);
                break;

            case "not_contains":
                expression = NotContains(type, rule.Value, propertyExp);
                break;

            case "ends_with":
                expression = EndsWith(type, rule.Value, propertyExp);
                break;

            case "not_ends_with":
                expression = NotEndsWith(type, rule.Value, propertyExp);
                break;

            case "is_empty":
                expression = IsEmpty(propertyExp);
                break;

            case "is_not_empty":
                expression = IsNotEmpty(propertyExp);
                break;

            case "is_null":
                expression = IsNull(propertyExp);
                break;

            case "is_not_null":
                expression = IsNotNull(propertyExp);
                break;

            default:
                throw new Exception($"Unknown expression operator: {rule.Operator}");
            }

            return(expression);
        }
Example #11
0
 public Filter(IFilterRule filterRule)
 {
     this.filterRule = filterRule ?? throw new ArgumentNullException(nameof(filterRule));
 }
Example #12
0
        private static Expression BuildElementAccessExpression(Expression expression, IEnumerator <string> propertyCollectionEnumerator, IFilterRule rule, BuildExpressionOptions options, Type type)
        {
            var propertyName = propertyCollectionEnumerator.Current;

            var leftBraceIndex  = propertyName.IndexOf("[");
            var rightBraceIndex = propertyName.IndexOf("]");

            if (leftBraceIndex > -1)
            {
                propertyName = propertyName.Substring(0, leftBraceIndex);
            }

            var propertyInfo       = expression.Type.GetProperty(propertyName);
            var propertyExpression = Expression.Property(expression, propertyInfo);

            var propertyType = propertyInfo.PropertyType;
            var dictionary   = propertyType.GetInterface("IDictionary`2");

            Type[] dictionaryTypes     = dictionary.GetGenericArguments();
            Type   dictionaryKeyType   = dictionaryTypes[0];
            Type   dictionaryValueType = dictionaryTypes[1];

            if (dictionaryKeyType != typeof(string))
            {
                throw new NotSupportedException("Only Dictionaries with string keys are supported at present.");
            }

            var dictionaryKeyValue = propertyCollectionEnumerator.Current.Substring(leftBraceIndex + 2, propertyCollectionEnumerator.Current.Length - leftBraceIndex - 4);

            PropertyInfo indexerProperty    = dictionary.GetProperty("Item");
            var          dictionaryKeyConst = Expression.Constant(dictionaryKeyValue);

            var indexExpression = Expression.MakeIndex(propertyExpression, indexerProperty, new[] { dictionaryKeyConst });

            return(indexExpression);
        }
Example #13
0
 public FilterRuleViewModel(FilterTypeViewModel type, IFilterRule rule)
 {
     Rule    = rule;
     Type    = type;
     Details = FilterFactory.GetRuleDetails(rule);
 }
 public Expression GetExpression(Type type, IFilterRule rule, Expression propertyExp, BuildExpressionOptions options)
 {
     return(Expression.Call(this.GetType().GetMethod("ContainsIP"), new[] { propertyExp, Expression.Constant(rule.Value) }));
 }
Example #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="filterRule"></param>
        /// <returns></returns>
        public static IQueryable BuildDynamicQuery(this IQueryable queryable, IFilterRule filterRule)
        {
            var returnValue = new ToStringQueryFiltering().ApplyFiltering(queryable, filterRule);

            return(returnValue);
        }