PredicateBuilder.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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> In<TV>(Expression<Func<T, TV>> selector, IEnumerable<TV> checkIn)
  16. {
  17. var c = Constant(checkIn.WrapEnumerable());
  18. var p = selector.Parameters[0];
  19. var call = Call(typeof(Enumerable), "Contains", new[] { typeof(TV) }, c, selector.Body);
  20. var exp = Lambda<Func<T, bool>>(call, p);
  21. return exp;
  22. }
  23. public PredicateWrap<T> NotIn<TV>(Expression<Func<T, TV>> selector, IEnumerable<TV> checkIn)
  24. {
  25. var p = selector.Parameters[0];
  26. var values = Constant(checkIn.WrapEnumerable());
  27. var @in = Call(typeof(Enumerable), "Contains", new[] { typeof(TV) }, values, selector.Body);
  28. var not = Not(@in);
  29. var exp = Lambda<Func<T, bool>>(not, p);
  30. return exp;
  31. }
  32. public PredicateWrap<T> StringContains(Expression<Func<T, string>> selector, string contains)
  33. {
  34. if (string.IsNullOrWhiteSpace(contains)) return null;
  35. var stringContainsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) })
  36. ?? throw new SystemException("ILL SYSTEM LIB? string.Contains(string) NOT EXIST??");
  37. var parameterExp = selector.Parameters[0];
  38. var valExp = Constant(contains, typeof(string));
  39. var callExp = Call(selector.Body, stringContainsMethod, valExp);
  40. var lambda = Lambda<Func<T, bool>>(callExp, parameterExp);
  41. return lambda;
  42. }
  43. public PredicateWrap<T> Between<TV>(Expression<Func<T, TV>> selector, TV min, TV max, bool include = true)
  44. {
  45. if (null == min && null == max) return null;
  46. PredicateWrap<T> predicateWrap = null;
  47. if (null != min)
  48. {
  49. predicateWrap = include
  50. ? GreaterThanOrEqual(selector, min)
  51. : GreaterThan(selector, min);
  52. }
  53. if (null != max)
  54. {
  55. predicateWrap &= include
  56. ? LessThanOrEqual(selector, max)
  57. : LessThan(selector, max);
  58. }
  59. return predicateWrap;
  60. }
  61. public PredicateWrap<T> Equal<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.Equal, selector, valueToCompare);
  62. public PredicateWrap<T> NotEqual<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.NotEqual, selector, valueToCompare);
  63. public PredicateWrap<T> LessThan<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.LessThan, selector, valueToCompare);
  64. public PredicateWrap<T> LessThanOrEqual<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.LessThanOrEqual, selector, valueToCompare);
  65. public PredicateWrap<T> GreaterThan<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.GreaterThan, selector, valueToCompare);
  66. public PredicateWrap<T> GreaterThanOrEqual<TV>(Expression<Func<T, TV>> selector, TV valueToCompare) => BinOp(Expression.GreaterThanOrEqual, selector, valueToCompare);
  67. private static PredicateWrap<T> BinOp<TV>(Func<Expression, Expression, Expression> op, Expression<Func<T, TV>> selector, TV valueToCompare)
  68. {
  69. var parameterExp = selector.Parameters[0];
  70. var valToCompareExp = Constant(valueToCompare, typeof(TV));
  71. var callExp = op(selector.Body, valToCompareExp);
  72. var lambda = Lambda<Func<T, bool>>(callExp, parameterExp);
  73. return lambda;
  74. }
  75. }
  76. }