PredicateBuilder.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using VCommon.Collections;
  6. using static System.Linq.Expressions.Expression;
  7. namespace VCommon.Linq.Expressions.Predicate
  8. {
  9. public sealed class PredicateBuilder<T>
  10. {
  11. public static readonly PredicateBuilder<T> Instance = new PredicateBuilder<T>();
  12. private PredicateBuilder()
  13. {
  14. }
  15. public PredicateWrap<T> Custom(Expression<Func<T, bool>> expression) => expression;
  16. public PredicateWrap<T> In<TV>(Expression<Func<T, TV>> selector, IEnumerable<TV> checkIn)
  17. {
  18. if (checkIn == null) return null;
  19. var c = Constant(checkIn.WrapEnumerable());
  20. var p = selector.Parameters[0];
  21. var call = Call(typeof(Enumerable), "Contains", new[] { typeof(TV) }, c, selector.Body);
  22. var exp = Lambda<Func<T, bool>>(call, p);
  23. return exp;
  24. }
  25. public PredicateWrap<T> NotIn<TV>(Expression<Func<T, TV>> selector, IEnumerable<TV> checkIn)
  26. {
  27. if (checkIn == null) return null;
  28. var p = selector.Parameters[0];
  29. var values = Constant(checkIn.WrapEnumerable());
  30. var @in = Call(typeof(Enumerable), "Contains", new[] { typeof(TV) }, values, selector.Body);
  31. var not = Not(@in);
  32. var exp = Lambda<Func<T, bool>>(not, p);
  33. return exp;
  34. }
  35. public PredicateWrap<T> StringContains(Expression<Func<T, string>> selector, string contains)
  36. {
  37. if (string.IsNullOrWhiteSpace(contains)) return null;
  38. var stringContainsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) })
  39. ?? throw new SystemException("ILL SYSTEM LIB? string.Contains(string) NOT EXIST??");
  40. var parameterExp = selector.Parameters[0];
  41. var valExp = Constant(contains, typeof(string));
  42. var callExp = Call(selector.Body, stringContainsMethod, valExp);
  43. var lambda = Lambda<Func<T, bool>>(callExp, parameterExp);
  44. return lambda;
  45. }
  46. public PredicateWrap<T> Between<TV>(Expression<Func<T, TV>> selector, TV min, TV max, bool include = true)
  47. {
  48. if (null == min && null == max) return null;
  49. PredicateWrap<T> predicateWrap = null;
  50. if (null != min)
  51. {
  52. predicateWrap = include
  53. ? GreaterThanOrEqual(selector, min)
  54. : GreaterThan(selector, min);
  55. }
  56. if (null != max)
  57. {
  58. predicateWrap &= include
  59. ? LessThanOrEqual(selector, max)
  60. : LessThan(selector, max);
  61. }
  62. return predicateWrap;
  63. }
  64. public PredicateWrap<T> Equal<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.Equal, selector, valueToCompare);
  65. public PredicateWrap<T> NotEqual<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.NotEqual, selector, valueToCompare);
  66. public PredicateWrap<T> LessThan<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.LessThan, selector, valueToCompare);
  67. public PredicateWrap<T> LessThanOrEqual<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.LessThanOrEqual, selector, valueToCompare);
  68. public PredicateWrap<T> GreaterThan<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.GreaterThan, selector, valueToCompare);
  69. public PredicateWrap<T> GreaterThanOrEqual<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.GreaterThanOrEqual, selector, valueToCompare);
  70. private static PredicateWrap<T> BinOp<TV>(Func<Expression, Expression, Expression> op, Expression<Func<T, TV>> selector, TV valueToCompare)
  71. {
  72. var parameterExp = selector.Parameters[0];
  73. var valToCompareExp = Constant(valueToCompare, typeof(TV));
  74. var callExp = op(selector.Body, valToCompareExp);
  75. var lambda = Lambda<Func<T, bool>>(callExp, parameterExp);
  76. return lambda;
  77. }
  78. }
  79. }