using Mapster;
namespace Dpz.Core.Service.Mediator;
public static class PageExtensions
{
/// <param name="source">包含所有要分页数据的IMongoQueryable对象。</param>
/// <typeparam name="TSource">原类型</typeparam>
extension<TSource>(IQueryable<TSource> source)
{
/// <summary>
/// 根据当前页索引pageIndex及每页记录数pageSize获取要分页的ViewModel数据对象。
/// </summary>
/// <typeparam name="TDestination">目标类型</typeparam>
/// <param name="pageIndex">当前页索引。</param>
/// <param name="pageSize">每页显示的记录数。</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IPagedList<TDestination>> ToPagedListAsync<TDestination>(
int pageIndex,
int pageSize,
CancellationToken cancellationToken = default
)
{
if (pageIndex < 1)
{
pageIndex = 1;
}
var itemIndex = (pageIndex - 1) * pageSize;
var totalItemCount = await source.CountAsync(cancellationToken: cancellationToken);
while (totalItemCount <= itemIndex && pageIndex > 1)
{
itemIndex = (--pageIndex - 1) * pageSize;
}
var pageOfItems = source.Skip(itemIndex).Take(pageSize);
var data = (await pageOfItems.ToListAsync(cancellationToken: cancellationToken)).Adapt<
List<TDestination>
>();
return new PagedList<TDestination>(data, pageIndex, pageSize, totalItemCount);
}
}
extension<TSource>(IQueryable<TSource> source)
{
public async Task<List<TDestination>> ToListAsync<TDestination>(
CancellationToken cancellationToken = default
)
{
var data = await source.ToListAsync(cancellationToken: cancellationToken);
return data.Adapt<List<TDestination>>();
}
public async Task<IPagedList<TSource>> ToPagedListAsync(
int pageIndex,
int pageSize,
CancellationToken cancellationToken = default
)
{
if (pageIndex < 1)
{
pageIndex = 1;
}
var itemIndex = (pageIndex - 1) * pageSize;
var totalItemCount = await source.CountAsync(cancellationToken: cancellationToken);
while (totalItemCount <= itemIndex && pageIndex > 1)
{
itemIndex = (--pageIndex - 1) * pageSize;
}
var pageOfItems = source.Skip(itemIndex).Take(pageSize);
var data = await pageOfItems.ToListAsync(cancellationToken: cancellationToken);
return new PagedList<TSource>(data, pageIndex, pageSize, totalItemCount);
}
public async Task<IPagedList<TDestination>> ToPagedListAsync<TDestination>(
int pageIndex,
int pageSize,
Func<TSource, TDestination> func,
CancellationToken cancellationToken = default
)
{
if (pageIndex < 1)
{
pageIndex = 1;
}
var itemIndex = (pageIndex - 1) * pageSize;
var totalItemCount = await source.CountAsync(cancellationToken: cancellationToken);
while (totalItemCount <= itemIndex && pageIndex > 1)
{
itemIndex = (--pageIndex - 1) * pageSize;
}
var pageOfItems = source.Skip(itemIndex).Take(pageSize);
var data = await pageOfItems.ToListAsync(cancellationToken: cancellationToken);
return new PagedList<TDestination>(
data.Select(func),
pageIndex,
pageSize,
totalItemCount
);
}
}
extension<TSource>(IFindFluent<TSource, TSource> source)
{
public async Task<PagedList<TDestination>> ToPagedListAsync<TDestination>(
int pageIndex,
int pageSize,
CancellationToken cancellationToken = default
)
{
if (pageIndex < 1)
{
pageIndex = 1;
}
var itemIndex = (pageIndex - 1) * pageSize;
var totalItemCount = checked((int)await source.CountDocumentsAsync(cancellationToken));
while (totalItemCount <= itemIndex && pageIndex > 1)
{
itemIndex = (--pageIndex - 1) * pageSize;
}
var pageOfItems = source.Skip(itemIndex).Limit(pageSize);
var data = (await pageOfItems.ToListAsync(cancellationToken: cancellationToken)).Adapt<
List<TDestination>
>();
return new PagedList<TDestination>(data, pageIndex, pageSize, totalItemCount);
}
public async Task<PagedList<TSource>> ToPagedListAsync(
int pageIndex,
int pageSize,
CancellationToken cancellationToken = default
)
{
if (pageIndex < 1)
{
pageIndex = 1;
}
var itemIndex = (pageIndex - 1) * pageSize;
var totalItemCount = checked((int)await source.CountDocumentsAsync(cancellationToken));
while (totalItemCount <= itemIndex && pageIndex > 1)
{
itemIndex = (--pageIndex - 1) * pageSize;
}
var pageOfItems = source.Skip(itemIndex).Limit(pageSize);
var data = await pageOfItems.ToListAsync(cancellationToken: cancellationToken);
return new PagedList<TSource>(data, pageIndex, pageSize, totalItemCount);
}
}
public static IPagedList<T> ToPagedList<T>(
this IEnumerable<T> source,
int pageIndex,
int pageSize,
int totalItem
)
{
return new PagedList<T>(source, pageIndex, pageSize, totalItem);
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
代码解释
这是一个C#静态扩展类,提供了分页查询和对象映射的功能。主要用于简化数据查询时的分页和类型转换操作。
主要功能模块
1. IQueryable 扩展(第一组)
extension<TSource>(IQueryable<TSource> source)
提供 ToPagedListAsync<TDestination> 方法:
- 功能:从 IQueryable 数据源获取分页数据,并使用 Mapster 将结果映射为目标类型
- 参数:
pageIndex: 当前页码(从1开始)pageSize: 每页记录数cancellationToken: 取消令牌
- 核心逻辑:
- 页码校验(小于1时重置为1)
- 计算跳过的记录数
- 获取总记录数
- 自动调整页码:如果计算的起始索引超出总记录数,自动回退到有效页
- 使用
Skip和Take实现分页 - 使用 Mapster 的
Adapt方法进行对象映射
2. IQueryable 扩展(第二组)
提供三个重载方法:
a. ToListAsync<TDestination>
- 将查询结果转换为列表并映射为目标类型
b. ToPagedListAsync (无类型转换)
- 返回原类型的分页数据,不进行对象映射
c. ToPagedListAsync<TDestination> (使用自定义转换函数)
- 接受
Func<TSource, TDestination>委托 - 使用自定义函数进行类型转换(而非 Mapster)
3. IFindFluent<TSource, TSource> 扩展
专门为 MongoDB 查询设计的扩展方法:
两个重载方法:
ToPagedListAsync<TDestination>: 带类型映射ToPagedListAsync: 不进行类型映射
关键差异:
- 使用
CountDocumentsAsync获取总数(MongoDB 特定) - 使用
Limit代替Take(MongoDB 语法) - 使用
checked防止整数溢出
4. IEnumerable 扩展
public static IPagedList<T> ToPagedList<T>(...)
- 用于已加载到内存的数据集合
- 直接封装为分页对象,不执行异步查询
关键设计特点
- 智能页码调整:当请求的页码超出范围时自动回退到最后一页
- 类型映射集成:深度集成 Mapster 对象映射库
- 多数据源支持:同时支持 EF Core (IQueryable) 和 MongoDB (IFindFluent)
- 异步优先:所有数据库操作均为异步方法
- 取消令牌支持:所有异步方法支持操作取消
语法说明
代码使用了 C# 扩展方法的非标准语法 extension<T>,这可能是:
- 某个预处理器或代码生成工具的语法
- 自定义的语法糖
- 标准写法应该是:
public static ... 方法名(this IQueryable<TSource> source, ...)
依赖项
- Mapster:对象映射库
- Entity Framework Core:
IQueryable.CountAsync、ToListAsync - MongoDB.Driver:
IFindFluent、CountDocumentsAsync
AI 正在分析代码…
评论加载中...