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

  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. 〖Linux〗ltib的使用帮助

    scue@Link:/home/work/ltib$ ./ltib --help This script is used to manage the building of BSPs with com ...

  2. 携程实时大数据平台演进:1/3 Storm应用已迁到JStorm

    携程大数据平台负责人张翼分享携程的实时大数据平台的迭代,按照时间线介绍采用的技术以及踩过的坑.携程最初基于稳定和成熟度选择了Storm+Kafka,解决了数据共享.资源控制.监控告警.依赖管理等问题之 ...

  3. ios开发-Object-C可变参数函数

    简介 一个可变参数函数是指一个函数拥有不定的参数,即为一个函数可接收多个参数.有时我们会遇到一些算术问题需要用到,比如是计算传入参数的总和,字符串的连接或是其它操作过程,我们在 OC 里也经常使用,最 ...

  4. javascript获取地址栏参数

    http://gzycm520.blog.51cto.com/175220/71030方法一: <script type="text/javascript"> < ...

  5. PHP安全细节(转)

    一个常见的PHP安全细则 发布时间:2012-01-09 10:18:50   来源:51cto   评论:0 点击:9 次 [字号:大 中 小] PHP本身再老版本有一些问题,比如在 php4.3. ...

  6. checkboxlist 横向显示,自动换行

    属性RepeatDirection 设为Horizontal RepeatColumns设置一个数字,表示每行显示几项 如果不想让每行显示的项是固定的,那么把RepeatLayout属性置为Flow

  7. 用bcdedit.exe重建bcd

    使用下面方法之前需要bcdedit.exe和bootsect.exe两个文件,bootsect.exe文件在vista和windows 7的安装光盘的boot目录下,而bcdedit.exe文件可以在 ...

  8. unity, public+[HideInInspector] vs private

    下面写法不报错: [System.Serializable] public class CmyObj{ CA m_a; ... } public class XXX: MonoBehavior{ [H ...

  9. 收集整理的mybatis资料

    这是个系列文章,讲的非常不错 mybatis 详解(一)------JDBC  https://www.cnblogs.com/ysocean/p/7271600.html mybatis  http ...

  10. 使用802.1X+FreeRadius+LDAP实现网络准入方案

    前言:在很多运维项目交流中,我们发现有一些运维团队还是在尝试使用网管或桌面管理来进行网络准入管理,但这两个技术有一定的缺点,所以本文分享一下802.1X+开源软件整合的网络准入管理的实践. 网络准入业 ...