Ardalis.Specification 用于 C# (.NET):完整指南及示例
\n\n在现代 C# (.NET) 开发中,关键任务之一是组织干净、可测试且可维护的数据处理代码。规范模式(Specification Pattern)是一个强大的工具,它允许将业务规则和查询逻辑封装为可重用、可组合且可测试的类。Ardalis.Specification 库是在 .NET 生态系统中实现该模式的事实标准,为开发者提供了一种优雅的方式来抽象特定的 ORM(如 Entity Framework Core、Dapper 等),并构建灵活的数据查询。
\n\n为什么需要它?在使用 Entity Framework Core 的典型应用程序中,查询逻辑常常分散在代码各处:控制器、服务、仓储中。这会导致代码重复(例如,同一个“活跃用户”过滤器可能在不同地方重复出现)、测试困难(需要模拟 DbContext)以及脆弱性(修改一个查询可能会破坏另一个)。Ardalis.Specification 通过提供统一、强类型的方式来描述需要获取哪些数据,而不依赖于具体如何获取这些数据,从而解决了这些问题。
\n\n该库提供了丰富的 API 来构建查询:从简单的过滤(Where)到复杂的关联数据包含(Include、ThenInclude)、排序(OrderBy、ThenBy)、分页(Skip、Take)和投影(Select)。它与 Entity Framework Core 完全兼容(通过 Ardalis.Specification.EntityFrameworkCore 包),但也可以适配其他数据提供程序。因此,您的代码变得更清晰,查询逻辑可重用,测试也大大简化。
\n\n安装
\n使用 NuGet 安装该库。根据您的 ORM,需要安装主包和提供程序包。
\n# 主包(包含基类和接口)\ndotnet add package Ardalis.Specification\n\n# Entity Framework Core 包(包含仓储实现)\ndotnet add package Ardalis.Specification.EntityFrameworkCore\n\n# 如果您仅使用基础包而不使用 EF Core(例如,用于测试或自定义实现)\ndotnet add package Ardalis.Specification\n\n快速入门
\n让我们看一个最小的工作示例。假设我们有一个 Product 实体,并且想要获取所有价格大于 100 的产品。
// 1. 定义实体\npublic class Product\n{\n public int Id { get; set; }\n public string Name { get; set; } = string.Empty;\n public decimal Price { get; set; }\n public bool IsActive { get; set; }\n}\n\n// 2. 创建规范\npublic class ProductsWithPriceGreaterThanSpec : Specification<Product>\n{\n public ProductsWithPriceGreaterThanSpec(decimal minPrice)\n {\n Query.Where(p => p.Price > minPrice);\n }\n}\n\n// 3. 使用规范与仓储\npublic class ProductService\n{\n private readonly IRepositoryBase<Product> _repository;\n\n public ProductService(IRepositoryBase<Product> repository)\n {\n _repository = repository;\n }\n\n public async Task<List<Product>> GetExpensiveProductsAsync(decimal minPrice)\n {\n var spec = new ProductsWithPriceGreaterThanSpec(minPrice);\n return await _repository.ListAsync(spec);\n }\n}\n\n在这个示例中,我们创建了一个规范类,它封装了过滤逻辑。仓储 IRepositoryBase(来自 Ardalis.Specification.EntityFrameworkCore 包)会自动将此规范应用于您的 DbContext 并返回结果。这就是该模式的精髓:将查询描述与其执行分离。
主要方法和类
\n该库