入门:
https://www.cnblogs.com/FlyEdward/archive/2010/01/28/Linq_ExpressionTree1.html
深入:
https://www.cnblogs.com/Terrylee/archive/2008/08/01/custom-linq-provider-part-1-expression-tree.html
应用:
https://www.yycoding.xyz/post/2020/9/22/an-introduction-to-csharp-expression-tree-build-dynamic-queries
(1)参照以上自己用表达式树实现一个分页:
分页集合类: public class PagedList<T> : List<T> { public int CurrentPage { get; set; } public int PageSize { get; set; } public int TotalPages { get; set; } QueryOptions Options { get; set; } public bool HasPreviousPage; public bool HasNextPage; public PagedList(IQueryable<T> query, QueryOptions o) { CurrentPage = o.CurrentPage; PageSize = o.PageSize; Options = o; HasPreviousPage = CurrentPage > 1; HasNextPage = CurrentPage < TotalPages; if (o != null) { if (o.OrderByPropertyNameIsDescending!=null) { query = o.OrderByPropertyNameIsDescending.Aggregate(query, (total, next) => Order(total, next.Key, next.Value)); } if (o.SearchPropertyNameByValue!=null) { query = o.SearchPropertyNameByValue.Aggregate(query, (total, next) => Search(total, next.Key, next.Value)); } } TotalPages = query.Count() / PageSize == 0 ? 1 : query.Count() / PageSize; AddRange(query.Skip((CurrentPage - 1) * PageSize).Take(PageSize)); } private IQueryable<T> Search(IQueryable<T> query, string searchPropertyName, string searchItem) { var parameter = Expression.Parameter(typeof(T), "x"); var source = searchPropertyName.Split('.').Aggregate((Expression)parameter, Expression.Property); var body = Expression.Call(source, "Contains", Type.EmptyTypes, Expression.Constant(searchItem, typeof(string))); var lambda = Expression.Lambda<Func<T, bool>>(body, parameter); return query.Where(lambda); } private IQueryable<T> Order(IQueryable<T> query, string orderPropertyName, bool descendingOrder) { var parameter = Expression.Parameter(typeof(T), "x"); var source = Expression.Property(parameter, orderPropertyName); var lambda = Expression.Lambda(typeof(Func<,>).MakeGenericType(typeof(T), source.Type), source, parameter); return typeof(Queryable).GetMethods().Single(method => method.Name == (descendingOrder ? "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 class QueryOptions { public QueryOptions(int currentPage=1,int pageSize=30) { CurrentPage = currentPage; PageSize = pageSize; } public int CurrentPage { get; set; } public int PageSize { get; set; } public IDictionary<string, bool> OrderByPropertyNameIsDescending { get; set; } public IDictionary<string, string> SearchPropertyNameByValue { get; set; } }
调用方式:
class Program { static void Main(string[] args) { ///1.本地数据源延迟调用 List<Person> persons = new List<Person>() { new Person(){Name="张三",Age=65}, new Person(){Name="李四",Age=20}, new Person(){Name="李四2",Age=21} }; QueryOptions queryOption = new QueryOptions(); queryOption.PageSize = 50; queryOption.CurrentPage = 1; queryOption.OrderByPropertyNameIsDescending = new Dictionary<string, bool>() { { "Age", true } }; queryOption.SearchPropertyNameByValue = new Dictionary<string, string>() { { "Name", "李四" } }; PagedList<Person> pagelist = new PagedList<Person>(persons.AsQueryable<Person>(), queryOption); ///远程数据源延迟调用 queryOption.SearchPropertyNameByValue = new Dictionary<string, string>() { { "Name", "Frank" } }; using ( testDbEntities testDbEntities=new testDbEntities()) { PagedList<T_Person> pagelist2 = new PagedList<T_Person>(testDbEntities.T_Person, queryOption); } Console.ReadKey(); } } public class Person { public string Name { get; set; } public int Age { get; set; } public string Emaill { get; set; } }
///远程数据源 是EF连接的数据库数据集合