using System;
using System.Collections.Generic;
using System.Linq;
using MessagePack;
namespace Dpz.Core.Web.Pager;
/// <summary>
/// 表示包含分页数据对象的强类型列表。
/// </summary>
/// <typeparam name="T"></typeparam>
[MessagePackObject(keyAsPropertyName: true)]
public class PagedList<T> : List<T>, IPagedList<T>
{
/// <summary>
/// 使用要分页的所有数据项、当前页索引和每页显示的记录数初始化PagedList对象
/// </summary>
/// <param name="allItems">要分页的所有数据项</param>
/// <param name="pageIndex">当前页索引</param>
/// <param name="pageSize">每页显示的记录数</param>
public PagedList(IEnumerable<T> allItems, int pageIndex, int pageSize)
{
PageSize = pageSize;
var items = allItems as IList<T> ?? allItems.ToList();
TotalItemCount = items.Count();
CurrentPageIndex = pageIndex;
AddRange(items.Skip(StartItemIndex - 1).Take(pageSize));
}
/// <summary>
/// 使用当前页数据项、当前页索引、每页显示的记录数和要分页的总记录数初始化PagedList对象
/// </summary>
/// <param name="currentPageItems">当前页数据项</param>
/// <param name="pageIndex">当前页索引</param>
/// <param name="pageSize">每页显示的记录数</param>
/// <param name="totalItemCount">要分页数据的总记录数</param>
public PagedList(
IEnumerable<T> currentPageItems,
int pageIndex,
int pageSize,
int totalItemCount
)
{
AddRange(currentPageItems);
TotalItemCount = totalItemCount;
CurrentPageIndex = pageIndex;
PageSize = pageSize;
}
/// <summary>
/// 使用要分页的所有数据项、当前页索引和每页显示的记录数初始化PagedList对象
/// </summary>
/// <param name="allItems">要分页的所有数据项</param>
/// <param name="pageIndex">当前页索引</param>
/// <param name="pageSize">每页显示的记录数</param>
public PagedList(IQueryable<T> allItems, int pageIndex, int pageSize)
{
var startIndex = (pageIndex - 1) * pageSize;
AddRange(allItems.Skip(startIndex).Take(pageSize));
TotalItemCount = allItems.Count();
CurrentPageIndex = pageIndex;
PageSize = pageSize;
}
/// <summary>
/// 使用当前页数据项、当前页索引、每页显示的记录数和要分页的总记录数初始化PagedList对象
/// </summary>
/// <param name="currentPageItems">当前页数据项</param>
/// <param name="pageIndex">当前页索引</param>
/// <param name="pageSize">每页显示的记录数</param>
/// <param name="totalItemCount">要分页数据的总记录数</param>
public PagedList(
IQueryable<T> currentPageItems,
int pageIndex,
int pageSize,
int totalItemCount
)
{
AddRange(currentPageItems);
TotalItemCount = totalItemCount;
CurrentPageIndex = pageIndex;
PageSize = pageSize;
}
/// <summary>
/// 当前页索引
/// </summary>
[IgnoreMember]
public int CurrentPageIndex { get; set; }
/// <summary>
/// 每页显示的记录数
/// </summary>
[IgnoreMember]
public int PageSize { get; set; }
/// <summary>
/// 要分页的数据总数
/// </summary>
[IgnoreMember]
public int TotalItemCount { get; set; }
/// <summary>
/// 总页数
/// </summary>
[IgnoreMember]
public int TotalPageCount => (int)Math.Ceiling(TotalItemCount / (double)PageSize);
/// <summary>
/// 开始记录索引
/// </summary>
[IgnoreMember]
public int StartItemIndex => (CurrentPageIndex - 1) * PageSize + 1;
/// <summary>
/// 是否有上一页
/// </summary>
[IgnoreMember]
public bool HasNextPage => CurrentPageIndex < TotalPageCount;
/// <summary>
/// 结束记录索引
/// </summary>
[IgnoreMember]
public int EndItemIndex =>
TotalItemCount > CurrentPageIndex * PageSize ? CurrentPageIndex * PageSize : TotalItemCount;
public static PagedList<T> Empty() => new(new List<T>(), 0, 0);
public PagedList()
{
AddRange([]);
CurrentPageIndex = 0;
PageSize = 0;
}
public PagedListWarp<T> ToPagedListWarp()
{
return new PagedListWarp<T>(CurrentPageIndex, PageSize, TotalItemCount, this);
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
这是一个用于分页功能的泛型类 PagedList<T>,它实现了分页数据的封装和管理。让我详细解释一下这个代码:
类的基本结构
[MessagePackObject(keyAsPropertyName: true)]
public class PagedList<T> : List<T>, IPagedList<T>
- 继承自
List<T>,所以它本身就是一个列表,可以存储当前页的数据项 - 实现了
IPagedList<T>接口 - 使用了
MessagePackObject特性,支持序列化
构造函数
提供了4个重载构造函数和1个无参构造函数:
1. 从所有数据中分页(IEnumerable)
public PagedList(IEnumerable<T> allItems, int pageIndex, int pageSize)
- 接收所有数据,然后在内存中进行分页
- 使用
Skip和Take方法截取当前页数据
2. 直接提供当前页数据(IEnumerable)
public PagedList(IEnumerable<T> currentPageItems, int pageIndex, int pageSize, int totalItemCount)
- 直接接收已经分页好的当前页数据
- 适用于已经在数据库层面完成分页的场景
3. 从查询中分页(IQueryable)
public PagedList(IQueryable<T> allItems, int pageIndex, int pageSize)
- 针对数据库查询优化,延迟执行分页
- 先执行
Skip和Take,最后才执行Count()
4. 直接提供当前页查询(IQueryable)
public PagedList(IQueryable<T> currentPageItems, int pageIndex, int pageSize, int totalItemCount)
核心属性
所有属性都标记了 [IgnoreMember],表示在序列化时会被忽略:
CurrentPageIndex: 当前页索引PageSize: 每页显示的记录数TotalItemCount: 总记录数TotalPageCount: 总页数(计算属性)StartItemIndex: 当前页开始记录的索引EndItemIndex: 当前页结束记录的索引HasNextPage: 是否有下一页
计算逻辑
// 总页数计算
public int TotalPageCount => (int)Math.Ceiling(TotalItemCount / (double)PageSize);
// 开始索引计算(从1开始)
public int StartItemIndex => (CurrentPageIndex - 1) * PageSize + 1;
// 结束索引计算
public int EndItemIndex =>
TotalItemCount > CurrentPageIndex * PageSize ?
CurrentPageIndex * PageSize : TotalItemCount;
工具方法
Empty(): 创建一个空的分页列表ToPagedListWarp(): 转换为包装对象
使用场景
这个类特别适用于:
- Web应用的分页显示
- API返回分页数据
- 需要在内存中对数据进行分页处理
- 数据库查询结果的分页封装
设计优点
- 灵活性: 支持多种数据源(IEnumerable、IQueryable)
- 性能优化: 对IQueryable的处理考虑了延迟执行
- 易用性: 继承自List,可以直接当作列表使用
- 完整性: 提供了分页所需的所有计算属性
- 序列化支持: 支持MessagePack序列化
这是一个设计良好的分页工具类,能够满足大多数分页场景的需求。
AI 正在分析代码…
评论加载中...