Linq.Easy.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using System;
  2. using System.Collections.ObjectModel;
  3. using System.Linq.Expressions;
  4. using System.Reflection;
  5. namespace wispro.sp.utility
  6. {
  7. public class Query
  8. {
  9. public enum Operators
  10. {
  11. None = 0,
  12. Equal = 1,
  13. GreaterThan = 2,
  14. GreaterThanOrEqual = 3,
  15. LessThan = 4,
  16. LessThanOrEqual = 5,
  17. Contains = 6,
  18. StartWith = 7,
  19. EndWidth = 8,
  20. Range = 9
  21. }
  22. public enum Condition
  23. {
  24. OrElse = 1,
  25. AndAlso = 2
  26. }
  27. public string Name { get; set; }
  28. public Operators Operator { get; set; }
  29. public object Value { get; set; }
  30. public object ValueMin { get; set; }
  31. public object ValueMax { get; set; }
  32. public class QueryCollection : Collection<Query>
  33. {
  34. public Expression<Func<T, bool>> AsExpression<T>(Query.Condition? condition = Query.Condition.OrElse) where T : class
  35. {
  36. Type targetType = typeof(T);
  37. TypeInfo typeInfo = targetType.GetTypeInfo();
  38. var parameter = Expression.Parameter(targetType, "m");
  39. Expression expression = null;
  40. Func<Expression, Expression, Expression> Append = (exp1, exp2) =>
  41. {
  42. if (exp1 == null)
  43. {
  44. return exp2;
  45. }
  46. return (condition ?? Query.Condition.OrElse) == Query.Condition.OrElse ? Expression.OrElse(exp1, exp2) : Expression.AndAlso(exp1, exp2);
  47. };
  48. foreach (var item in this)
  49. {
  50. var property = typeInfo.GetProperty(item.Name);
  51. if (property == null ||
  52. !property.CanRead ||
  53. (item.Operator != Query.Operators.Range && item.Value == null) ||
  54. (item.Operator == Query.Operators.Range && item.ValueMin == null && item.ValueMax == null))
  55. {
  56. continue;
  57. }
  58. Type realType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
  59. if (item.Value != null)
  60. {
  61. item.Value = Convert.ChangeType(item.Value, realType);
  62. }
  63. Expression<Func<object>> valueLamba = () => item.Value;
  64. switch (item.Operator)
  65. {
  66. case Query.Operators.Equal:
  67. {
  68. expression = Append(expression, Expression.Equal(Expression.Property(parameter, item.Name),
  69. Expression.Convert(valueLamba.Body, property.PropertyType)));
  70. break;
  71. }
  72. case Query.Operators.GreaterThan:
  73. {
  74. expression = Append(expression, Expression.GreaterThan(Expression.Property(parameter, item.Name),
  75. Expression.Convert(valueLamba.Body, property.PropertyType)));
  76. break;
  77. }
  78. case Query.Operators.GreaterThanOrEqual:
  79. {
  80. expression = Append(expression, Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name),
  81. Expression.Convert(valueLamba.Body, property.PropertyType)));
  82. break;
  83. }
  84. case Query.Operators.LessThan:
  85. {
  86. expression = Append(expression, Expression.LessThan(Expression.Property(parameter, item.Name),
  87. Expression.Convert(valueLamba.Body, property.PropertyType)));
  88. break;
  89. }
  90. case Query.Operators.LessThanOrEqual:
  91. {
  92. expression = Append(expression, Expression.LessThanOrEqual(Expression.Property(parameter, item.Name),
  93. Expression.Convert(valueLamba.Body, property.PropertyType)));
  94. break;
  95. }
  96. case Query.Operators.Contains:
  97. {
  98. var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
  99. var contains = Expression.Call(Expression.Property(parameter, item.Name), "Contains", null,
  100. Expression.Convert(valueLamba.Body, property.PropertyType));
  101. expression = Append(expression, Expression.AndAlso(nullCheck, contains));
  102. break;
  103. }
  104. case Query.Operators.StartWith:
  105. {
  106. var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
  107. var startsWith = Expression.Call(Expression.Property(parameter, item.Name), "StartsWith", null,
  108. Expression.Convert(valueLamba.Body, property.PropertyType));
  109. expression = Append(expression, Expression.AndAlso(nullCheck, startsWith));
  110. break;
  111. }
  112. case Query.Operators.EndWidth:
  113. {
  114. var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
  115. var endsWith = Expression.Call(Expression.Property(parameter, item.Name), "EndsWith", null,
  116. Expression.Convert(valueLamba.Body, property.PropertyType));
  117. expression = Append(expression, Expression.AndAlso(nullCheck, endsWith));
  118. break;
  119. }
  120. case Query.Operators.Range:
  121. {
  122. Expression minExp = null, maxExp = null;
  123. if (item.ValueMin != null)
  124. {
  125. var minValue = Convert.ChangeType(item.ValueMin, realType);
  126. Expression<Func<object>> minValueLamda = () => minValue;
  127. minExp = Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(minValueLamda.Body, property.PropertyType));
  128. }
  129. if (item.ValueMax != null)
  130. {
  131. var maxValue = Convert.ChangeType(item.ValueMax, realType);
  132. Expression<Func<object>> maxValueLamda = () => maxValue;
  133. maxExp = Expression.LessThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(maxValueLamda.Body, property.PropertyType));
  134. }
  135. if (minExp != null && maxExp != null)
  136. {
  137. expression = Append(expression, Expression.AndAlso(minExp, maxExp));
  138. }
  139. else if (minExp != null)
  140. {
  141. expression = Append(expression, minExp);
  142. }
  143. else if (maxExp != null)
  144. {
  145. expression = Append(expression, maxExp);
  146. }
  147. break;
  148. }
  149. }
  150. }
  151. if (expression == null)
  152. {
  153. return null;
  154. }
  155. return ((Expression<Func<T, bool>>)Expression.Lambda(expression, parameter));
  156. }
  157. }
  158. }
  159. }