问题来源:前端文本输入框以分隔符(比如"aa|bb|cc")传进来的字符串,针对一个字段做的查询条件;由于该字符串分隔符数量不确定,因此需要动态构建出来;
旨在实现例如以下效果:
var users = await _context.Users.Where(s=>s.Name.Contains("aa") || s.Name.Contains("bb") || s.Name.Contains("cc")).ToListAsync();
以下是后端代码的相关实现
1.新建两个类如下:
public class PredicateExpressionVisitor : ExpressionVisitor { public ParameterExpression _parameter { get; set; } public PredicateExpressionVisitor(ParameterExpression parameter) { _parameter = parameter; } protected override Expression VisitParameter(ParameterExpression p) { return _parameter; } public override Expression Visit(Expression expression) { //Visit会根据VisitParameter()方法返回的Expression进行相关变量替换 return base.Visit(expression); } } /// <summary> /// Linq表达式扩展方法 /// </summary> public static class PredicateExtensions { /// <summary> /// 以And合并单个表达式 /// 此处采用AndAlso实现“最短路径”,避免掉额外且不需要的比较运算式 /// </summary> public static Expression<Func<T, bool>> MergeAnd<T>(this Expression<Func<T, bool>> leftExpress, Expression<Func<T, bool>> rightExpress) { //声明传递参数(也就是表达式树里面的参数别名s) ParameterExpression parameter = Expression.Parameter(typeof(T), "s"); //统一管理参数,保证参数一致,否则会报错 var visitor = new PredicateExpressionVisitor(parameter); //表达式树内容 Expression left = visitor.Visit(leftExpress.Body); Expression right = visitor.Visit(rightExpress.Body); //合并表达式 return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left, right), parameter); } /// <summary> /// 以And合并多个表达式 /// 此处采用AndAlso实现“最短路径”,避免掉额外且不需要的比较运算式 /// </summary> public static Expression<Func<T, bool>> MergeAnd<T>(this Expression<Func<T, bool>> express, params Expression<Func<T, bool>>[] arrayExpress) { if (!arrayExpress?.Any() ?? true) return express; //声明传递参数(也就是表达式树里面的参数别名s) ParameterExpression parameter = Expression.Parameter(typeof(T), "s"); //统一管理参数,保证参数一致,否则会报错 var visitor = new PredicateExpressionVisitor(parameter); Expression<Func<T, bool>> result = null; //合并表达式 foreach (var curExpression in arrayExpress) { //表达式树内容 Expression left = visitor.Visit(result.Body); Expression right = visitor.Visit(curExpression.Body); result = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left, right), parameter); } return result; } /// <summary> /// 以Or合并表达式 /// 此处采用OrElse实现“最短路径”,避免掉额外且不需要的比较运算式 /// </summary> public static Expression<Func<T, bool>> MergeOr<T>(this Expression<Func<T, bool>> leftExpress, Expression<Func<T, bool>> rightExpress) { //声明传递参数(也就是表达式树里面的参数别名s) ParameterExpression parameter = Expression.Parameter(typeof(T), "s"); //统一管理参数,保证参数一致,否则会报错 var visitor = new PredicateExpressionVisitor(parameter); //表达式树内容 Expression left = visitor.Visit(leftExpress.Body); Expression right = visitor.Visit(rightExpress.Body); //合并表达式 return Expression.Lambda<Func<T, bool>>(Expression.OrElse(left, right), parameter); } /// <summary> /// 以Or合并多个表达式 /// 此处采用AndAlso实现“最短路径”,避免掉额外且不需要的比较运算式 /// </summary> public static Expression<Func<T, bool>> MergeOr<T>(this Expression<Func<T, bool>> express, params Expression<Func<T, bool>>[] arrayExpress) { if (!arrayExpress?.Any() ?? true) return express; //声明传递参数(也就是表达式树里面的参数别名s) ParameterExpression parameter = Expression.Parameter(typeof(T), "s"); //统一管理参数,保证参数一致,否则会报错 var visitor = new PredicateExpressionVisitor(parameter); Expression<Func<T, bool>> result = null; //合并表达式 foreach (var curExpression in arrayExpress) { //表达式树内容 Expression left = visitor.Visit(result.Body); Expression right = visitor.Visit(curExpression.Body); result = Expression.Lambda<Func<T, bool>>(Expression.OrElse(left, right), parameter); } return result; } }View Code
2.在对应的接口中调用就能实现功能了(这里的search.Name以分隔符|举例,比如"aa|bb|cc")
//在文件夹下所搜多个文件名包含的查询条件 if (!string.IsNullOrWhiteSpace(search.Name)) { var names = search.Name.Split('|').ToList(); Expression<Func<FileInfomation, bool>> expression = default; foreach (var name in names) { if (names.IndexOf(name) == 0) expression = s => s.Name.Contains(name); else { Expression<Func<FileInfomation, bool>> expressionNew = s => s.Name.Contains(name); expression = expression.MergeOr(expressionNew); } } fileInfos = fileInfos.Where(expression.Compile()).ToList(); }View Code
标签:parameter,Visit,构建,visitor,参数,动态,Expression,表达式 From: https://www.cnblogs.com/hypothesisxk/p/17754833.html