示例#1
0
 public static IQueryable <TSubject> AutoFilter <TSubject, TPredicate>(
     this IQueryable <TSubject> query,
     TPredicate predicate,
     Conventions.ComposeKind composeKind = Conventions.ComposeKind.And
     )
     where TSubject : class
 => Conventions <TSubject> .Filter(query, predicate, composeKind).OrderByConventions(predicate);
示例#2
0
        public static IQueryable <TSubject> Filter <TPredicate>(IQueryable <TSubject> query,
                                                                TPredicate predicate,
                                                                Conventions.ComposeKind composeKind = Conventions.ComposeKind.And)
        {
            var filterProps = FastTypeInfo <TPredicate>
                              .PublicProperties
                              .ToArray();

            var filterPropNames = filterProps
                                  .Select(x => x.Name)
                                  .ToArray();

            var modelType = typeof(TSubject);

            var parameter = Expression.Parameter(modelType);

            var props = FastTypeInfo <TSubject>
                        .PublicProperties
                        .Where(x => filterPropNames.Contains(x.Name))
                        .Select(x => new
            {
                Property = x,
                Value    = filterProps.Single(y => y.Name == x.Name).GetValue(predicate)
            })
                        .Where(x => x.Value != null)
                        .Select(x =>
            {
                var property     = Expression.Property(parameter, x.Property);
                Expression value = Expression.Constant(x.Value);

                value    = Expression.Convert(value, property.Type);
                var body = Conventions.Filters[property.Type](property, value);

                return(Expression.Lambda <Func <TSubject, Boolean> >(body, parameter));
            })
                        .ToArray();

            if (!props.Any())
            {
                return(query);
            }

            var expr = composeKind == Conventions.ComposeKind.And
                                ? props.Aggregate((c, n) => c.And(n))
                                : props.Aggregate((c, n) => c.Or(n));

            return(query.Where(expr));
        }
示例#3
0
        public static Expression <Func <TSubject, Boolean> > FilterExpression <TPredicate>(TPredicate predicate,
                                                                                           Conventions.ComposeKind composeKind = Conventions.ComposeKind.And
                                                                                           )
        {
            if (predicate == null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            // ищем беспараметрический конструктор
            var defaultPredicate = FastTypeInfo <TPredicate> .Constructors
                                   .Any(c => c.GetParameters().Length == 0) ?
                                   Activator.CreateInstance(typeof(TPredicate))
                                : null;

            // ***сравнение значений полей
            Boolean Equal(PropertyInfo pi, Object a, Object b)
            {
                if (a == null || b == null)
                {
                    return(false);
                }
                var aVal = pi.GetValue(a);
                var bVal = pi.GetValue(b);

                return(aVal != null?aVal.Equals(bVal) : bVal != null ? false : true);
            }

            // *** end Equal

            // фильтруем только по тем полям, значения которых отличны от дефолтных
            var filterProps = FastTypeInfo <TPredicate>
                              .PublicProperties
                              .Where(x => !Equal(x, predicate, defaultPredicate))
                              .ToArray();

            var filterPropNames = filterProps
                                  .Select(x => x.Name)
                                  .ToArray();

            var modelType = typeof(TSubject);

            var parameter = Expression.Parameter(modelType);

            var props = FastTypeInfo <TSubject>
                        .PublicProperties
                        .Where(x => filterPropNames.Contains(x.Name))
                        .Select(x => new
            {
                Property = x,
                Value    = filterProps.Single(y => y.Name == x.Name).GetValue(predicate)
            })
                        .Where(x => x.Value != null)
                        .Select(x =>
            {
                var property     = Expression.Property(parameter, x.Property);
                Expression value = Expression.Constant(x.Value);

                value    = Expression.Convert(value, property.Type);
                var body = Conventions.Filters[property.Type](property, value);

                return(Expression.Lambda <Func <TSubject, Boolean> >(body, parameter));
            })
                        .ToArray();

            if (!props.Any())
            {
                return(Expression.Lambda <Func <TSubject, Boolean> >(Expression.Constant(true), parameter));
            }

            var expr = composeKind == Conventions.ComposeKind.And
                                ? props.Aggregate((c, n) => c.And(n))
                                : props.Aggregate((c, n) => c.Or(n));

            return(expr);
        }