public FilterParameter[] ParseFilters(Type type, QueryParameter[] queryParameters) { var filters = new List <FilterParameter>(); var properties = _propertyCache.GetProperties(type); foreach (var propertyInfo in properties) { var filter = queryParameters.FirstOrDefault(q => string.Equals(q.Key, propertyInfo.Name, StringComparison.OrdinalIgnoreCase)); if (filter != null) { var opStr = queryParameters.FirstOrDefault(q => string.Equals($"{filter.Key}_op", q.Key, StringComparison.OrdinalIgnoreCase)); var op = Op.Equals; if (opStr != null) { op = ParseOperator(opStr.Value); } filters.Add(new FilterParameter(filter.Key, op, filter.Value, propertyInfo)); } var nullFilter = queryParameters.FirstOrDefault(q => q.Key.Equals($"{propertyInfo.Name}_op", StringComparison.OrdinalIgnoreCase) && (q.Value.Equals("isnull", StringComparison.OrdinalIgnoreCase) || q.Value.Equals("notnull", StringComparison.OrdinalIgnoreCase))); if (nullFilter != null) { filters.Add(new FilterParameter(propertyInfo.Name, ParseOperator(nullFilter.Value), nullFilter.Value, propertyInfo)); } } return(filters.ToArray()); }
public async Task <QueryResult <TEntity> > ApplyAsync <TEntity>(IQueryable <TEntity> entities, FilterParameter[] filters, SortParameter[] sorts, PaginationParameter pagination, CancellationToken cancellationToken) { if (filters != null && filters.Length > 0) { var propreties = _propertyCache.GetProperties <TEntity>(); var parameterExpression = Expression.Parameter(typeof(TEntity), "e"); Expression outerExpression = null; foreach (var filter in filters) { var property = propreties.FirstOrDefault(q => string.Equals(q.Name, filter.FieldName, StringComparison.OrdinalIgnoreCase)); if (property == null) { throw new ArgumentException($"Property for Filter.Field({filter.FieldName}) not found."); } var converter = TypeDescriptor.GetConverter(property.PropertyType); dynamic propertyValue = Expression.PropertyOrField(parameterExpression, property.Name); Expression innerExpression = null; if (filter.Op == Op.In) { foreach (var value in filter.Values) { dynamic constantVal = GetConstantVal <TEntity>(converter, value, property); Expression filterValue = Expression.Constant(constantVal, property.PropertyType); var filterExpression = GetBinaryExpression(Op.Equals, filterValue, propertyValue); innerExpression = innerExpression == null ? filterExpression : Expression.OrElse(innerExpression, filterExpression); } } else if (filter.Op == Op.Between) { dynamic leftConstantVal = GetConstantVal <TEntity>(converter, filter.Values[0], property); Expression leftFilterValue = Expression.Constant(leftConstantVal, property.PropertyType); dynamic rightConstantVal = GetConstantVal <TEntity>(converter, filter.Values[1], property); Expression rightFilterValue = Expression.Constant(rightConstantVal, property.PropertyType); innerExpression = Expression.And( GetBinaryExpression(Op.GreaterThanOrEqualTo, leftFilterValue, propertyValue), GetBinaryExpression(Op.LessThanOrEqualTo, rightFilterValue, propertyValue) ); } else if (filter.Op == Op.IsNull || filter.Op == Op.NotNull) { innerExpression = GetBinaryExpression(filter.Op, null, propertyValue); } else { dynamic constantVal = GetConstantVal <TEntity>(converter, filter.Values[0], property); Expression filterValue = Expression.Constant(constantVal, property.PropertyType); innerExpression = GetBinaryExpression(filter.Op, filterValue, propertyValue); } if (outerExpression == null) { outerExpression = innerExpression; } else { outerExpression = Expression.AndAlso(outerExpression, innerExpression); } } entities = outerExpression == null ? entities : entities.Where(Expression.Lambda <Func <TEntity, bool> >(outerExpression, parameterExpression)); } if (sorts != null && sorts.Length > 0) { var useThenBy = false; foreach (var sortParameter in sorts) { entities = OrderByDynamic(entities, sortParameter.Field, sortParameter.Desc, useThenBy); useThenBy = true; } } if (pagination != null) { var totalCount = entities.Count(); var result = await entities.Skip((pagination.PageNumber - 1) *pagination.PageSize) .Take(pagination.PageSize).ToArrayAsync(cancellationToken); return(new QueryResult <TEntity> { Data = result, TotalCount = totalCount, PageSize = pagination.PageSize, PageNumber = pagination.PageNumber }); } var data = await entities.ToArrayAsync(cancellationToken); return(new QueryResult <TEntity> { Data = data, TotalCount = data.Length }); }