/// <summary> /// Applies the given DynamicQueryOptions to the generic IEnumerable instace. /// </summary> /// <param name="currentSet">Existing IEnumerable instance.</param> /// <param name="dynamicQueryOptions">Query options to apply.</param> /// <returns>DynamicQueryOptions applied IEnumerable instance,</returns> public static IQueryable ApplyFilters(this IQueryable currentSet, DynamicQueryOptions dynamicQueryOptions) { try { if (dynamicQueryOptions == null || currentSet == null) { return(currentSet); } Expression exp = null; // Create the query parameter ParameterExpression param = Expression.Parameter(currentSet.ElementType, currentSet.ElementType.Name.ToLower()); if (dynamicQueryOptions.Filters != null && dynamicQueryOptions.Filters.Count > 0) { // Copy the array since we need to mutate it, we should avoid mutating the real list. List <Filter> dqbFilters = dynamicQueryOptions.Filters.ToList(); // Since the expression is null at this point, we should create it with our first filter. exp = BuildFilterExpression(param, dqbFilters.FirstOrDefault(), dynamicQueryOptions.UsesCaseInsensitiveSource); dqbFilters.RemoveAt(0); // Remove the first since it was added already. // Append the rest foreach (Filter item in dqbFilters) { exp = Expression.AndAlso(exp, BuildFilterExpression(param, item, dynamicQueryOptions.UsesCaseInsensitiveSource)); } } if (dynamicQueryOptions.SortOptions != null && dynamicQueryOptions.SortOptions.Count > 0) { List <OrderOptionDetails> orderLambdas = new List <OrderOptionDetails>(); foreach (SortOption so in dynamicQueryOptions.SortOptions) { Expression paramExpr = ExtractMember(param, so.PropertyName); orderLambdas.Add(new OrderOptionDetails { Direction = so.SortingDirection, Expression = Expression.Lambda(paramExpr, param), ParameterExpression = paramExpr, CaseSensitive = so.CaseSensitive }); } var orderVisitor = new OrderFunctionVisitor( currentSet.Expression, orderLambdas, currentSet.ElementType, dynamicQueryOptions.UsesCaseInsensitiveSource, dynamicQueryOptions.IgnorePredefinedOrders); currentSet = currentSet.Provider.CreateQuery(orderVisitor.ApplyOrders()); } if (exp != null) { MethodCallExpression whereFilter = Expression.Call( LINQUtils.BuildLINQExtensionMethod( nameof(Enumerable.Where), genericElementTypes: new[] { currentSet.ElementType }, enumerableType: typeof(Queryable)), currentSet.Expression, Expression.Quote(Expression.Lambda(exp, param))); currentSet = currentSet.Provider.CreateQuery(whereFilter); } if (dynamicQueryOptions.PaginationOption != null) { if (dynamicQueryOptions.PaginationOption.AssignDataSetCount) { dynamicQueryOptions.PaginationOption.DataSetCount = (int)_countFunction.Invoke(null, new[] { currentSet }); } if (dynamicQueryOptions.PaginationOption.Offset > 0) { MethodCallExpression skip = Expression.Call( _skipFunction, currentSet.Expression, Expression.Constant(dynamicQueryOptions.PaginationOption.Offset)); currentSet = currentSet.Provider.CreateQuery(skip); } if (dynamicQueryOptions.PaginationOption.Count > 0) { MethodCallExpression take = Expression.Call( _takeFunction, currentSet.Expression, Expression.Constant(dynamicQueryOptions.PaginationOption.Count)); currentSet = currentSet.Provider.CreateQuery(take); } } return(currentSet); } catch (Exception ex) { throw new DynamicQueryException("DynamicQueryBuilder has encountered an unhandled exception", string.Empty, ex); } }
/// <summary> /// Applies the given DynamicQueryOptions to the generic IEnumerable instace. /// </summary> /// <param name="currentSet">Existing IEnumerable instance.</param> /// <param name="dynamicQueryOptions">Query options to apply.</param> /// <returns>DynamicQueryOptions applied IEnumerable instance,</returns> public static IQueryable ApplyFilters(this IQueryable currentSet, DynamicQueryOptions dynamicQueryOptions) { try { if (dynamicQueryOptions == null || currentSet == null) { return(currentSet); } Expression exp = null; // Create the query parameter (x =>) ParameterExpression param = Expression.Parameter(currentSet.ElementType, currentSet.ElementType.Name.ToLower()); // Check if we have any filters if (dynamicQueryOptions.Filters != null && dynamicQueryOptions.Filters.Count > 0) { // Lets build the first expression and then iterate the rest and append them to this one exp = BuildFilterExpression(param, dynamicQueryOptions.Filters.First(), dynamicQueryOptions.UsesCaseInsensitiveSource); // We start to iterate with the second element here because we have just built the first expression up above for (int i = 1; i < dynamicQueryOptions.Filters.Count; ++i) { // Build the current expression Expression builtExpression = BuildFilterExpression(param, dynamicQueryOptions.Filters[i], dynamicQueryOptions.UsesCaseInsensitiveSource); // Get the previous filter to retrieve the logical operator between the current and the next filter Filter previousFilter = dynamicQueryOptions.Filters.ElementAtOrDefault(i - 1); exp = LINQUtils.BuildLINQLogicalOperatorExpression(previousFilter, exp, builtExpression); } } if (dynamicQueryOptions.SortOptions != null && dynamicQueryOptions.SortOptions.Count > 0) { var orderLambdas = new List <OrderOptionDetails>(); foreach (SortOption so in dynamicQueryOptions.SortOptions) { Expression paramExpr = ExtractMember(param, so.PropertyName, false); orderLambdas.Add(new OrderOptionDetails { Direction = so.SortingDirection, Expression = Expression.Lambda(paramExpr, param), ParameterExpression = paramExpr, CaseSensitive = so.CaseSensitive }); } var orderVisitor = new OrderFunctionVisitor( currentSet.Expression, orderLambdas, currentSet.ElementType, dynamicQueryOptions.UsesCaseInsensitiveSource, dynamicQueryOptions.IgnorePredefinedOrders); currentSet = currentSet.Provider.CreateQuery(orderVisitor.ApplyOrders()); } if (exp != null) { MethodCallExpression whereFilter = Expression.Call( LINQUtils.BuildLINQExtensionMethod( nameof(Enumerable.Where), genericElementTypes: new[] { currentSet.ElementType }, enumerableType: typeof(Queryable)), currentSet.Expression, Expression.Quote(Expression.Lambda(exp, param))); currentSet = currentSet.Provider.CreateQuery(whereFilter); } if (dynamicQueryOptions.PaginationOption != null) { if (dynamicQueryOptions.PaginationOption.AssignDataSetCount) { dynamicQueryOptions.PaginationOption.DataSetCount = (int)ExtensionMethods.CountFunction.Invoke(null, new[] { currentSet }); } if (dynamicQueryOptions.PaginationOption.Offset > 0) { MethodCallExpression skip = Expression.Call( ExtensionMethods.SkipFunction, currentSet.Expression, Expression.Constant(dynamicQueryOptions.PaginationOption.Offset)); currentSet = currentSet.Provider.CreateQuery(skip); } if (dynamicQueryOptions.PaginationOption.Count > 0) { MethodCallExpression take = Expression.Call( ExtensionMethods.TakeFunction, currentSet.Expression, Expression.Constant(dynamicQueryOptions.PaginationOption.Count)); currentSet = currentSet.Provider.CreateQuery(take); } } return(currentSet); } catch (Exception ex) { throw new DynamicQueryException("DynamicQueryBuilder has encountered an unhandled exception", string.Empty, ex); } }