Predicator.cs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. using System;
  2. using System.Linq;
  3. using System.Linq.Expressions;
  4. namespace SKMC.Api.Common
  5. {
  6. public static class Predicator
  7. {
  8. public static Expression<Func<T, bool>> GetTrue<T>() { return f => true; }
  9. public static Expression<Func<T, bool>> GetFalse<T>() { return f => false; }
  10. public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
  11. {
  12. return first.AndAlso<T>(second, Expression.AndAlso);
  13. }
  14. public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
  15. {
  16. return first.AndAlso<T>(second, Expression.OrElse);
  17. }
  18. private static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2, Func<Expression, Expression, BinaryExpression> func)
  19. {
  20. var parameter = Expression.Parameter(typeof(T));
  21. var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
  22. var left = leftVisitor.Visit(expr1.Body);
  23. var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
  24. var right = rightVisitor.Visit(expr2.Body);
  25. return Expression.Lambda<Func<T, bool>>(
  26. func(left, right), parameter);
  27. }
  28. public static Expression<Func<T, bool>> AggregateAnd<T>(Expression<Func<T, bool>>[] input)
  29. {
  30. return input.Aggregate((l, r) => l.And(r));
  31. }
  32. private class ReplaceExpressionVisitor : ExpressionVisitor
  33. {
  34. private readonly Expression _oldValue;
  35. private readonly Expression _newValue;
  36. public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
  37. {
  38. _oldValue = oldValue;
  39. _newValue = newValue;
  40. }
  41. public override Expression Visit(Expression node)
  42. {
  43. if (node == _oldValue)
  44. return _newValue;
  45. return base.Visit(node);
  46. }
  47. }
  48. }
  49. }