PredicateBuilder.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Text;
  6. namespace Ant.Service.Common
  7. {
  8. /// <summary>
  9. /// 谓词表达式构建器
  10. /// add 作者: 季健国 QQ:181589805 by 2016-09-08
  11. /// </summary>
  12. public static class PredicateBuilder
  13. {
  14. /// <summary>
  15. /// 机关函数应用True时:单个AND有效,多个AND有效;单个OR无效,多个OR无效;混应时写在AND后的OR有效
  16. /// </summary>
  17. /// <typeparam name="T"></typeparam>
  18. /// <returns></returns>
  19. public static Expression<Func<T, bool>> True<T>() { return f => true; }
  20. /// <summary>
  21. /// 机关函数应用False时:单个AND无效,多个AND无效;单个OR有效,多个OR有效;混应时写在OR后面的AND有效
  22. /// </summary>
  23. /// <typeparam name="T"></typeparam>
  24. /// <returns></returns>
  25. public static Expression<Func<T, bool>> False<T>() { return f => false; }
  26. public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
  27. Expression<Func<T, bool>> expr2)
  28. {
  29. return expr1.Compose(expr2, Expression.Or);
  30. }
  31. public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
  32. Expression<Func<T, bool>> expr2)
  33. {
  34. return expr1.Compose(expr2, Expression.And);
  35. }
  36. public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
  37. {
  38. // build parameter map (from parameters of second to parameters of first)
  39. var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
  40. // replace parameters in the second lambda expression with parameters from the first
  41. var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
  42. // apply composition of lambda expression bodies to parameters from the first expression
  43. return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
  44. }
  45. }
  46. public class ParameterRebinder : ExpressionVisitor
  47. {
  48. private readonly Dictionary<ParameterExpression, ParameterExpression> map;
  49. public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
  50. {
  51. this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
  52. }
  53. public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
  54. {
  55. return new ParameterRebinder(map).Visit(exp);
  56. }
  57. protected override Expression VisitParameter(ParameterExpression p)
  58. {
  59. ParameterExpression replacement;
  60. if (map.TryGetValue(p, out replacement))
  61. {
  62. p = replacement;
  63. }
  64. return base.VisitParameter(p);
  65. }
  66. }
  67. }