Lambda表达式动态组装查询条件
最近比较闲,年底了,项目也进入尾声;每天就是维护一下系统,整理整理文档,整理知识点,这样才觉得有点意思;
问题
在使用Linq的where()查询的时候,不知道大家是怎么动态组装多个查询条件时,是怎么做的?我是这样做的,请看下面代码;
方法一:
1.1 Expression的扩展类
public static class PredicateExtensions { public static Expression<Func<T, bool>> True<T>() { return f => true; } public static Expression<Func<T, bool>> False<T>() { return f => false; } public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters); } public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());//将一个委托或lambda表达式应用于参数表达式列表。 return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters); } }
1.2 实例化代码
List<string> strList = new List<string>() { "郑州","上海户口", "鲁山揽锅菜", "南京酸菜鱼" }; //传统写法 Func<string, bool> func = (t) => t.Length > 3&&t.Contains("鱼"); var listA=strList.Where(func).ToList(); //使用扩展写法 var expression=PredicateExtensions.True<string>(); expression = expression.And(t => t.Length > 3); expression = expression.And(t => t.Contains("鱼")); var predicate = expression.Compile(); var listB = strList.Where(predicate).ToList();
方法二:合并两个Expression表达式
2.1 表达式参数扩展类
public class MyExpressionVisitor:ExpressionVisitor { private readonly ParameterExpression _parameter; public MyExpressionVisitor(ParameterExpression parameter) { _parameter = parameter; } public ParameterExpression Parameter { get { return _parameter; } } public Expression Nodify(Expression exp) { Expression e = this.Visit(exp); return e; } protected override Expression VisitParameter(ParameterExpression node) { return _parameter; } }
2.2 实例化代码
int[] numbers = { 19, 25, 6, 8, 49, 7, 8, 0, 1, 47, 35, 30,29 }; //表达式一 ParameterExpression leftPara = Expression.Parameter(typeof(int), "n"); Expression a_con = Expression.Constant(13); BinaryExpression a_binary = Expression.GreaterThan(leftPara, a_con); var a_lambda = Expression.Lambda<Func<int, bool>>(a_binary,leftPara); var a_result = a_lambda.Compile(); var a_list = numbers.Where(a_result).ToList(); //表达式二 ParameterExpression b_leftPara = Expression.Parameter(typeof(int), "n"); Expression b_con = Expression.Constant(30); BinaryExpression b_binary = Expression.LessThanOrEqual(b_leftPara, b_con); var b_lambda = Expression.Lambda<Func<int, bool>>(b_binary, b_leftPara); var b_result = b_lambda.Compile(); var b_list = numbers.Where(b_result).ToList(); //合并两个表达式 var vistor = new MyExpressionVisitor(leftPara); Expression c_1 = vistor.Nodify(a_lambda.Body); Expression c_2 = vistor.Nodify(b_lambda.Body); BinaryExpression c_binary = Expression.AndAlso(c_1, c_2); var c_lambda = Expression.Lambda<Func<int, bool>>(c_binary, leftPara); var c_result = c_lambda.Compile();//编译表达式 var c_list = numbers.Where(c_result).ToList();
方法二有点啰嗦,当时是用表达式树来创建的;大家可以用匿名表达式简单一点。但是在合并表达式的逻辑是,重新更改了一下表达式一和表达式二的参数,这样在编译的时候就可以通过了。
写的不咋样,日日精进吧。。。。