今天发表了《将不确定变为确定~表达式树是否可以有个集合,条件过滤有了新方向》文章后,马上有朋友问起,如何实现OR查询,如果实现AND查询,事实上它说的可能并不完整,完整的话应该是,“如何实现N个字段进行OR运算和AND运算”呢,没错,我在那篇文章中,条件过滤只是针对单个字段的,是一种AND运算,也是一种条件的过滤机制,即:
有条件a1,a2,a3,它的过滤方式是先过滤a1,然后在剩下的结果里过滤a2,最后再过滤a3,它相然等同于a1 && a2 && a3,但如果要实现OR运算,我的那个程序就无能为力了,看看我们伟大的JamesJim同志写的这个OR与AND为表达式树实现的扩展方法吧,呵呵 。
1 /// <summary> 2 /// 条件建立者 3 /// [单元表达式主要考用用在数据库字段或是其他集合字段中考用直接返回bool查询的] 4 /// [考用考虑,如果一个内存集合中,考用定义一个属性,属性中有逻辑,例如:return str.Lenght==1;这样的可以用到单元运算符。] 5 /// </summary> 6 public static class PredicateBuilder 7 { 8 /// <summary> 9 /// 单元 true 表达式 10 /// </summary> 11 /// <typeparam name="T">指定泛型 T</typeparam> 12 /// <returns>true</returns> 13 public static Expression<Func<T, bool>> True<T>() 14 { 15 return item => true; 16 } 17 18 /// <summary> 19 /// 单元 false 表达式 20 /// </summary> 21 /// <typeparam name="T">指定泛型 T</typeparam> 22 /// <returns>false</returns> 23 public static Expression<Func<T, bool>> False<T>() 24 { 25 return item => false; 26 } 27 28 /// <summary> 29 /// 双元 Or 表达式 30 /// </summary> 31 /// <typeparam name="T">指定泛型 T</typeparam> 32 /// <param name="exprleft">左表达式</param> 33 /// <param name="exprright">右表达式</param> 34 /// <returns>返回合并表达式</returns> 35 public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> exprleft, Expression<Func<T, bool>> exprright) 36 { 37 var invokedExpr = Expression.Invoke(exprright, exprleft.Parameters.Cast<Expression>()); 38 return Expression.Lambda<Func<T, bool>>(Expression.Or(exprleft.Body, invokedExpr), exprleft.Parameters); 39 } 40 41 /// <summary> 42 /// 双元 And 表达式 43 /// </summary> 44 /// <typeparam name="T">指定泛型 T</typeparam> 45 /// <param name="exprleft">左表达式</param> 46 /// <param name="exprright">右表达式</param> 47 /// <returns>返回合并表达式</returns> 48 public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> exprleft, Expression<Func<T, bool>> exprright) 49 { 50 var invokedExpr = Expression.Invoke(exprright, exprleft.Parameters.Cast<Expression>()); 51 return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(exprleft.Body, invokedExpr), exprleft.Parameters); 52 } 53 }
再配合我的统一条件功能类,进行一下改造:
1 /// <summary> 2 /// 功能:条件过滤类 3 /// 作者:张占岭 4 /// 日期:2012-6-7 5 /// </summary> 6 public class PredicateList<TEntity> : IEnumerable<Expression<Func<TEntity, bool>>> where TEntity : class 7 { 8 List<Expression<Func<TEntity, bool>>> expressionList; 9 public PredicateList() 10 { 11 expressionList = new List<Expression<Func<TEntity, bool>>>(); 12 } 13 /// <summary> 14 /// 添加到集合 15 /// </summary> 16 /// <param name="predicate"></param> 17 public void Add(Expression<Func<TEntity, bool>> predicate) 18 { 19 expressionList.Add(predicate); 20 } 21 /// <summary> 22 /// Or操作添加到集合 23 /// </summary> 24 /// <param name="exprleft"></param> 25 /// <param name="exprright"></param> 26 public void AddForOr(Expression<Func<TEntity, bool>> exprleft, Expression<Func<TEntity, bool>> exprright) 27 { 28 expressionList.Add(exprleft.Or(exprright)); 29 } 30 /// <summary> 31 /// And操作添加到集合 32 /// </summary> 33 /// <param name="exprleft"></param> 34 /// <param name="exprright"></param> 35 public void AddForAnd(Expression<Func<TEntity, bool>> exprleft, Expression<Func<TEntity, bool>> exprright) 36 { 37 expressionList.Add(exprleft.And(exprright)); 38 } 39 40 #region IEnumerable 成员 41 42 public IEnumerator GetEnumerator() 43 { 44 return expressionList.GetEnumerator(); 45 } 46 47 #endregion 48 49 #region IEnumerable<Expression<Func<TEntity>>> 成员 50 51 IEnumerator<Expression<Func<TEntity, bool>>> IEnumerable<Expression<Func<TEntity, bool>>>.GetEnumerator() 52 { 53 return expressionList.GetEnumerator(); 54 } 55 56 #endregion 57 }
嘿嘿,这样就可以把一些用到做AND或者OR的条件先进行组成,最后再和其它条件一起过滤,就OK了,呵呵。
调用时,可以这样:
1 PredicateList<UserBases> zzl = new PredicateList<UserBases>(); 2 Expression<Func<UserBases, bool>> exp_name = i => i.Name.Contains("zzl"); 3 Expression<Func<UserBases, bool>> exp_id = i => i.UserID == 1; 4 zzl.AddForOr(exp_name, exp_id); 5 GetModel(zzl).ForEach(i => Console.WriteLine(i.Name)); 6 Console.ReadKey();
OK,世界上对于i.Name和i.UserID的赋值,是我们在业务上判断过的,在PredicateList中存在的过滤条件就是真实要被过滤的。
本文转自博客园张占岭(仓储大叔)的博客,原文链接:将不确定变为确定~表达式树是否可以有个集合,条件过滤有了新方向续(新增了OR和AND查询),如需转载请自行联系原博主。