动态构建表达式树,最佳实践版,很实用!

  1. public class FilterCollection : Collection<IList<Filter>>
  2. {
  3. public FilterCollection()
  4. : base()
  5. { }
  6. }
  7. public class Filter
  8. {
  9. public string PropertyName { get; set; }
  10. public Op Operation { get; set; }
  11. public object Value { get; set; }
  12. }
  13. public enum Op
  14. {
  15. Equals,
  16. GreaterThan,
  17. LessThan,
  18. GreaterThanOrEqual,
  19. LessThanOrEqual,
  20. Contains,
  21. StartsWith,
  22. EndsWith
  23. }

通过上面的类可以动态构建复杂的查询条件,下面具体调用的类哦

  1. using Infrastructure.Model;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Reflection;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. namespace Infrastructure.Operation
  10. {
  11. public static class LambdaExpressionBuilder
  12. {
  13. private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");
  14. private static MethodInfo startsWithMethod =
  15. typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
  16. private static MethodInfo endsWithMethod =
  17. typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
  18. private static Expression GetExpression(ParameterExpression param, Filter filter)
  19. {
  20. MemberExpression member = Expression.Property(param, filter.PropertyName);
  21. Expression handledMember = member;
  22. ConstantExpression constant = Expression.Constant(filter.Value);
  23. if (member.Member.MemberType == MemberTypes.Property)
  24. {
  25. Type propertyType = ((PropertyInfo)member.Member).PropertyType;
  26. if (propertyType == typeof(string))
  27. {
  28. handledMember = Expression.Call(member, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
  29. }
  30. if (propertyType == typeof(DateTime?))
  31. {
  32. handledMember = Expression.Property(member, typeof(DateTime?).GetProperty("Value"));
  33. }
  34. }
  35. switch (filter.Operation)
  36. {
  37. case Op.Equals:
  38. return Expression.Equal(handledMember, constant);
  39. case Op.GreaterThan:
  40. return Expression.GreaterThan(handledMember, constant);
  41. case Op.GreaterThanOrEqual:
  42. return Expression.GreaterThanOrEqual(handledMember, constant);
  43. case Op.LessThan:
  44. return Expression.LessThan(handledMember, constant);
  45. case Op.LessThanOrEqual:
  46. return Expression.LessThanOrEqual(handledMember, constant);
  47. case Op.Contains:
  48. return Expression.Call(handledMember, containsMethod, constant);
  49. case Op.StartsWith:
  50. return Expression.Call(handledMember, startsWithMethod, constant);
  51. case Op.EndsWith:
  52. return Expression.Call(handledMember, endsWithMethod, constant);
  53. }
  54. return null;
  55. }
  56. private static BinaryExpression GetORExpression(ParameterExpression param, Filter filter1, Filter filter2)
  57. {
  58. Expression bin1 = GetExpression(param, filter1);
  59. Expression bin2 = GetExpression(param, filter2);
  60. return Expression.Or(bin1, bin2);
  61. }
  62. private static Expression GetExpression(ParameterExpression param, IList<Filter> orFilters)
  63. {
  64. if (orFilters.Count == 0)
  65. return null;
  66. Expression exp = null;
  67. if (orFilters.Count == 1)
  68. {
  69. exp = GetExpression(param, orFilters[0]);
  70. }
  71. else if (orFilters.Count == 2)
  72. {
  73. exp = GetORExpression(param, orFilters[0], orFilters[1]);
  74. }
  75. else
  76. {
  77. while (orFilters.Count > 0)
  78. {
  79. var f1 = orFilters[0];
  80. var f2 = orFilters[1];
  81. if (exp == null)
  82. {
  83. exp = GetORExpression(param, orFilters[0], orFilters[1]);
  84. }
  85. else
  86. {
  87. exp = Expression.Or(exp, GetORExpression(param, orFilters[0], orFilters[1]));
  88. }
  89. orFilters.Remove(f1);
  90. orFilters.Remove(f2);
  91. if (orFilters.Count == 1)
  92. {
  93. exp = Expression.Or(exp, GetExpression(param, orFilters[0]));
  94. orFilters.RemoveAt(0);
  95. }
  96. }
  97. }
  98. return exp;
  99. }
  100. public static Expression<Func<T, bool>> GetExpression<T>(FilterCollection filters)
  101. {
  102. if (filters == null || filters.Count == 0)
  103. return null;
  104. ParameterExpression param = Expression.Parameter(typeof(T), "t");
  105. Expression exp = null;
  106. if (filters.Count == 1)
  107. {
  108. exp = GetExpression(param, filters[0]);
  109. }
  110. else if (filters.Count == 2)
  111. {
  112. exp = Expression.AndAlso(GetExpression(param, filters[0]), GetExpression(param, filters[1]));
  113. }
  114. else
  115. {
  116. while (filters.Count > 0)
  117. {
  118. var f1 = filters[0];
  119. var f2 = filters[1];
  120. var f1Andf2 = Expression.AndAlso(GetExpression(param, filters[0]), GetExpression(param, filters[1]));
  121. if (exp == null)
  122. {
  123. exp = f1Andf2;
  124. }
  125. else
  126. {
  127. exp = Expression.AndAlso(exp, f1Andf2);
  128. }
  129. filters.Remove(f1);
  130. filters.Remove(f2);
  131. if (filters.Count == 1)
  132. {
  133. exp = Expression.AndAlso(exp, GetExpression(param, filters[0]));
  134. filters.RemoveAt(0);
  135. }
  136. }
  137. }
  138. return Expression.Lambda<Func<T, bool>>(exp, param);
  139. }
  140. }
  141. }

再来一个OrderBy动态构建

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using System.Text;
  7. namespace Jurassic.Sooil.Com
  8. {
  9. public static class OrderExpression
  10. {
  11. public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
  12. {
  13. return ApplyOrder<T>(source, property, "OrderBy");
  14. }
  15. public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
  16. {
  17. return ApplyOrder<T>(source, property, "OrderByDescending");
  18. }
  19. public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
  20. {
  21. return ApplyOrder<T>(source, property, "ThenBy");
  22. }
  23. public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
  24. {
  25. return ApplyOrder<T>(source, property, "ThenByDescending");
  26. }
  27. static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
  28. {
  29. string[] props = property.Split('.');
  30. Type type = typeof(T);
  31. ParameterExpression arg = Expression.Parameter(type, "x");
  32. Expression expr = arg;
  33. foreach (string prop in props)
  34. {
  35. // use reflection (not ComponentModel) to mirror LINQ
  36. PropertyInfo pi = type.GetProperty(prop);
  37. expr = Expression.Property(expr, pi);
  38. type = pi.PropertyType;
  39. }
  40. Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
  41. LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
  42. object result = typeof(Queryable).GetMethods().Single(
  43. method => method.Name == methodName
  44. && method.IsGenericMethodDefinition
  45. && method.GetGenericArguments().Length == 2
  46. && method.GetParameters().Length == 2)
  47. .MakeGenericMethod(typeof(T), type)
  48. .Invoke(null, new object[] { source, lambda });
  49. return (IOrderedQueryable<T>)result;
  50. }
  51. }
  52. }

至此动态构建LINQ查询结束!花了上班时间一上午,还是相当值得的,不过被项目经理知道了得哭死!

不管如何,学到手的才是自己的!

表达式树在LINQ动态查询的更多相关文章

  1. c#——表达式树在LINQ动态查询

    一般如果逻辑比较简单,只是存在有的情况多一个查询条件,有的情况不需要添加该查询条件 简单方式这样操作就可以了 public IQueryable<FileImport> DynamicCh ...

  2. Linq动态查询与模糊查询 ---转

    Linq动态查询与模糊查询(带源码示例) 继LINQ动态组合查询PredicateExtensions讲解 ----- 在用上面的方法时遇到了些问题 解决 LINQ to Entities 不支持 L ...

  3. Linq动态查询简易解决之道(原创)

    因为项目需要使用Linq来查询数据,但是在多条件查询时,需要使用一大堆if(...!=string.empty)等判断条件感觉不是很优雅.网上搜索以下,大概找到了两种办法,一种是老外写的一个类,感觉用 ...

  4. Linq 动态查询排序

    Linq的排序一般是这样写的: query.OrderBy(x => x.Tel).Skip().Take(); 实际使用中排序字段可能是通过字符类型的参数来设置的,于是想这样实现: query ...

  5. 洛谷3834 hdu2665主席树模板,动态查询区间第k小

    题目链接:https://www.luogu.com.cn/problem/P3834 对于区间查询第k小的问题,在区间数量达到5e5的时候是难以用朴素数据结构实现的,这时候主席树就应运而生了,主席树 ...

  6. Linq动态查询

    public class ExpressionCall { List<Customer> customers = new List<Customer>() { new Cust ...

  7. linq字符串搜索条件,排序条件-linq动态查询语句 Dynamic LINQ

    在做搜索和排序的时候,往往是前台传过来的字符串做条件,参数的数量还不定,这就需要用拼sql语句一样拼linq语句.而linq语句又是强类型的,不能用字符串拼出来. 现在好了,有个开源的linq扩展方法 ...

  8. LINQ动态查询类--[DynamicLinqExpressions]

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.L ...

  9. 转载:C#特性-表达式树

    原文地址:http://www.cnblogs.com/tianfan/ 表达式树基础 刚接触LINQ的人往往觉得表达式树很不容易理解.通过这篇文章我希望大家看到它其实并不像想象中那么难.您只要有普通 ...

随机推荐

  1. java 清单文件

    Java之jar打包 标签: javajarmanifestmain-classclass-path 2016-03-30 00:29 993人阅读 评论(0) 收藏 举报  分类: Java(6)  ...

  2. Ubuntu14.04上深度学习Caffe库安装指南(CUDA7.5 + opencv3.1)

    Ubuntu14.04上Caffe安装指南 安装的准备工作 首先,安装官方版Caffe时.假设要使用Cuda.须要确认自己确实有NVIDIA GPU. 安装Ubuntu时,将/boot 分区分大概20 ...

  3. springmvc 日期解决方案(三)使用jackson

    引入jar包: <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jac ...

  4. 计划任务 crontab

    1.

  5. EMQ配置

    参考官方配置页面:http://emqtt.com/docs/v2/tune.html Linux 操作系统参数系统所有进程可打开的文件数量官方配置: sysctl -w fs.file-max=20 ...

  6. EMQ学习---客户链接资源消耗

    Erlang进程消耗EMQ对客户端链接使用链接进程(emqtt_client)和session进程(emqtt_session)分开的策略. 当一个mqtt的客户端连接到EMQ的服务器上的时候,首先会 ...

  7. 使用sqlplus连接提示:ORA-28002: the password will expire within 7 days

    今天在使用sqlplus时出现,或使用数据库的时候出现类似问题 =============================================== ERROR:ORA-28002: the ...

  8. numpy和matplotlib绘制直方图

    使用 Matplotlib Matplotlib 中有直方图绘制函数:matplotlib.pyplot.hist()它可以直接统计并绘制直方图.你应该使用函数 calcHist() 或 np.his ...

  9. unity, multi collider

    比如下面鸭子模型,只用一个box collider难以很好地吻合其的外形. 我们可以为它添加两个box collider,如下图所示: 注意: 1,colliders一定要添加在模型根节点(即图中do ...

  10. Atitit.500 503 404错误处理最佳实践oak

    Atitit.500 503 404错误处理最佳实践oak 1. 错误处理的流程(捕获>>日志>>db>>email alert) 1 2. 错误的捕获:strut ...