如何动态构建Or组合的Expression<Func<T,bool>>实现多子串搜索
解决方案
要实现多子串或原串的OR匹配,同时保留品牌ID过滤,需要通过动态构建表达式树组合多个Contains条件,具体实现如下:
完整实现代码
using System.Linq.Expressions; using System.Collections.Generic; public class ProductsSpecification : BaseSpecifcation<Product> { public ProductsSpecification(ProductSpecParams productParams) : base(BuildFinalCriteria(productParams)) { } private static Expression<Func<Product, bool>> BuildFinalCriteria(ProductSpecParams productParams) { // 1. 整理所有需要匹配的关键词:原串+拆分后的子串(自动去重) var searchTerms = new HashSet<string>(); if (!string.IsNullOrEmpty(productParams.Search)) { searchTerms.Add(productParams.Search.ToLower()); foreach (var term in productParams.Search.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { searchTerms.Add(term.ToLower()); } } // 2. 构建品牌过滤基础条件 Expression<Func<Product, bool>> brandCriteria = x => !productParams.BrandId.HasValue || x.ProductBrandId == productParams.BrandId; // 无搜索关键词时直接返回品牌条件 if (!searchTerms.Any()) { return brandCriteria; } // 3. 构建搜索条件的OR组合 Expression<Func<Product, bool>> searchCriteria = x => false; foreach (var term in searchTerms) { var currentTerm = term; // 避免闭包陷阱,确保每个表达式捕获独立的关键词 Expression<Func<Product, bool>> termExpr = x => x.Name.ToLower().Contains(currentTerm); // 用OR合并当前关键词条件与已有的搜索条件 searchCriteria = Expression.Lambda<Func<Product, bool>>( Expression.OrElse(searchCriteria.Body, termExpr.Body), searchCriteria.Parameters.Single() ); } // 4. 合并搜索条件与品牌条件(AND关系) return Expression.Lambda<Func<Product, bool>>( Expression.AndAlso(searchCriteria.Body, brandCriteria.Body), searchCriteria.Parameters.Single() ); } }
核心细节说明
- 关键词去重:用
HashSet存储关键词,自动剔除重复项,避免生成冗余的匹配条件 - 闭包陷阱处理:循环中通过
currentTerm变量捕获当前迭代的关键词,防止所有表达式引用同一个变量导致逻辑错误 - 表达式树拼接:通过
Expression.OrElse组合多个搜索条件(实现sub1 || sub2 || sub3 || 原串),再用Expression.AndAlso与品牌过滤条件组合(实现(搜索条件) && (品牌条件))
内容的提问来源于stack exchange,提问作者x19
相关产品推荐
相关产品推荐

