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

  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. MIME protocol 说明

    按照 <张孝祥Java邮件开发详解> 自己create了 emali, 其中jpg 和wav文件格式过大,删除了写内容 From redhat@diego.com Mon Nov 17 0 ...

  2. NSArray利用Cocoa框架进行汉字排序

    NSArray利用Cocoa框架进行汉字排序 在NSString有一个函数localizedCompare:,它的功能是通过自身与给定字符串的比較,返回一个本地化的比較结果.也就是说这个函数是支持汉字 ...

  3. knockoutjs 静动态数据、行为绑定,计算属性及Sync同步更新 Value值更新事件控制

    data-bind="text: firstName"中data-bind属性是Knockout 用来显示关联UI和viewmodel的桥梁, text 表示把绑定的文本赋值给DO ...

  4. css实现图片水平垂直居中

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. MS SQL自定义函数IsPositiveInteger MS SQL自定义函数IsNumeric 水晶报表使用IEnumerable<T>数据源

    MS SQL自定义函数IsPositiveInteger   判断字符串是否为正整数,0开始的的数字不算. SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON ...

  6. STL六大组件简介

    一.STL简介 (一).泛型程序设计 泛型编程(generic programming) 将程序写得尽可能通用 将算法从数据结构中抽象出来,成为通用的 C++的模板为泛型程序设计奠定了关键的基础 (二 ...

  7. export、exports、modules.exports 和 require 、import 的一些组合套路和坑

    推荐阅读第三方文章: http://www.tuicool.com/articles/uuUVBv2 引入: require / import 导出:export / module.exports / ...

  8. Python实现百度搜索并保存到本地示例,Python实现百度搜索

    实现百度搜索并保存到本地 User_Agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko ...

  9. AutoFac文档3(转载)

    目录 开始 Registering components 控制范围和生命周期 用模块结构化Autofac xml配置 与.net集成 深入理解Autofac 指导 关于 词汇表 服务类型,名称和键 同 ...

  10. 阿里云maven 库

    阿里云maven 库 , 好用,速度快 maven setting.xml https://github.com/ae6623/Zebra/blob/master/maven-repo-setting ...