using System.Collections.Generic;
using System.Linq;
using System;
using System.Linq.Expressions;
using System.Diagnostics;
namespace SportsStore.Models.Pages {
public class PagedList<T> : List<T> {
public PagedList(IQueryable<T> query, QueryOptions options = null) {
CurrentPage = options.CurrentPage;
PageSize = options.PageSize;
Options = options;
if (options != null) {
if (!string.IsNullOrEmpty(options.OrderPropertyName)) {
query = Order(query, options.OrderPropertyName,
options.DescendingOrder);
}
if (!string.IsNullOrEmpty(options.SearchPropertyName)
&& !string.IsNullOrEmpty(options.SearchTerm)) {
query = Search(query, options.SearchPropertyName,
options.SearchTerm);
}
}
//Stopwatch sw = Stopwatch.StartNew();
//Console.Clear();
TotalPages = query.Count() / PageSize;
AddRange(query.Skip((CurrentPage - 1) * PageSize).Take(PageSize));
//Console.WriteLine($"Query Time: {sw.ElapsedMilliseconds} ms");
}
public int CurrentPage { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public QueryOptions Options { get; set; }
public bool HasPreviousPage => CurrentPage > 1;
public bool HasNextPage => CurrentPage < TotalPages;
private static IQueryable<T> Search(IQueryable<T> query, string propertyName,
string searchTerm) {
var parameter = Expression.Parameter(typeof(T), "x");
var source = propertyName.Split('.').Aggregate((Expression) parameter,
Expression.Property);
var body = Expression.Call(source, "Contains", Type.EmptyTypes,
Expression.Constant(searchTerm, typeof(string)));
var lambda = Expression.Lambda<Func<T, bool>>(body, parameter);
return query.Where(lambda);
}
private static IQueryable<T> Order(IQueryable<T> query, string propertyName,
bool desc) {
var parameter = Expression.Parameter(typeof(T), "x");
var source = propertyName.Split('.').Aggregate((Expression) parameter,
Expression.Property);
var lambda = Expression.Lambda(typeof(Func<,>).MakeGenericType(typeof(T),
source.Type), source, parameter);
return typeof(Queryable).GetMethods().Single(
method => method.Name == (desc ? "OrderByDescending"
: "OrderBy")
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), source.Type)
.Invoke(null, new object[] { query, lambda }) as IQueryable<T>;
}
}
}
public PagedList<Category> GetCategories(QueryOptions options) {
return new PagedList<Category>(context.Categories, options);
}
namespace SportsStore.Models.Pages {
public class QueryOptions {
public int CurrentPage { get; set; } = 1;
public int PageSize { get; set; } = 10;
public string OrderPropertyName { get; set; }
public bool DescendingOrder { get; set; }
public string SearchPropertyName { get; set; }
public string SearchTerm { get; set; }
}
}