c# 扩展方法 奇思妙用 高级篇 九:OrderBy(string propertyName, bool desc)
下面是 Queryable 类 中最常用的两个排序的扩展方法:
1 |
public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector); |
算上另外两个复杂点的,一共是四个方法,都是强类型的。
虽然强类型优点多多,但有些情况下确显得不够灵活。
强类型的缺点
比如 web 应用中有如下 Url:
在代码中我们如何写出强类型的查询?
1 |
IQueryable<Order> query = /**/; |
单凭 Queryable 类 中定义的 OrderBy 和 OrderByDescending, 是不可能简单直接写出来的,除非硬编码。
那有如此做到灵活呢?我们从 Queryable 类 定义的 OrderBy 和 OrderByDescending 方法下手,它们均有一个 Expression<Func<TSource, TKey>> 类型的 keySelector 参数。
先来试下能不能动态构建一个 keySelector。
动态构建 keySelector 参数
此部分要求对表达式树有一定了解,可查看:http://msdn.microsoft.com/zh-cn/library/bb397951(v=VS.100).aspx
代码则相当简单:
1 |
var type = typeof(Order); |
最后三行代码动态构造了一颗表达式树:
和我们使用 lambda 表达式写出的效果是完全一样的:
这步比较顺利,下面来看如何调用:
调用 OrderBy
直接传入调用是不行的:
1 |
repository.OrderBy(keySelector); |
因为前面构建的 keySelector 是 LambdaExpression类型的,而 OrderBy 要求是 Expression<Func<Order, DateTime>> 。
但实质上 keySelector 就是 OrderBy 要求的类型:
因为强类型,居然不认自家人了!
可以通过强制类型转换来解决,编译运行都没问题:
1 |
repository.OrderBy((Expression<Func<Order, DateTime>>)keySelector); |
但这样一来,又成了硬编码。
我们期望灵活,解决方法有很多种,这里只介绍最简单的一种,借助 .net 4 中 dynamic:
1 |
var orderedQueryable = Queryable.OrderBy(repository, (dynamic)keySelector); |
因为扩展方法是不能被动态调用的(Extension methods cannot be dynamically dispatched),所以写成上面样子。
或将 keySelector 声明为 dynamic:
1 |
dynamic keySelector = Expression.Lambda(body, param); |
OK,搞定!根据属性名排序太常用了,遂提取成了扩展方法:
OrderBy 扩展方法
将上面代码整理下,扩展方法就出来了:
1 |
public static class QueryableExtensions { |
注意,上面代码执行没问题,但效率不好。因为每次都要动态生成表达式树,另外动态调用也会造成一定性能损失。
想提高效率的话,可把动态生成的表达式树缓存起来,参考如下:
1 |
public static class QueryableExtensions { |
这里并发不是多大问题,如若考虑,可使用 ConcurrentDictionary<TKey, TValue> 类。
使用
很方便的:
1 |
var data1 = productRepository.OrderBy("Name"); |
http://www.cnblogs.com/ldp615/archive/2012/01/15/orderby-extensions.html
c# 扩展方法 奇思妙用 高级篇 九:OrderBy(string propertyName, bool desc)的更多相关文章
- C# 扩展方法奇思妙用高级篇六:WinForm 控件选择器
在Web开发中,jQuery提供了功能异常强大的$选择器来帮助我们获取页面上的对象.但在WinForm中,.Net似乎没有这样一个使用起来比较方便的选择器.好在我们有扩展方法,可以很方便的打造一个. ...
- c# 扩展方法奇思妙用基础篇九:Expression 扩展
http://www.cnblogs.com/ldp615/archive/2011/09/15/expression-extension-methods.html .net 中创建 Expressi ...
- c# 扩展方法奇思妙用基础篇八:Distinct 扩展(转载)
转载地址:http://www.cnblogs.com/ldp615/archive/2011/08/01/distinct-entension.html 刚看了篇文章 <Linq的Distin ...
- c# 扩展方法奇思妙用基础篇八:Distinct 扩展
刚看了篇文章 <Linq的Distinct太不给力了>,文中给出了一个解决办法,略显复杂. 试想如果能写成下面的样子,是不是更简单优雅 var p1 = products.Distinct ...
- c# 扩展方法奇思妙用基础篇五:Dictionary<TKey, TValue> 扩展
Dictionary<TKey, TValue>类是常用的一个基础类,但用起来有时确不是很方便.本文逐一讨论,并使用扩展方法解决. 向字典中添加键和值 添加键和值使用 Add 方法,但很多 ...
- c# 扩展方法奇思妙用
# 扩展方法出来已久,介绍扩展方法的文章也很多,但都是笼统的.本人最近一直在思考扩展方法的应用,也悟出了一些,准备将这最近一段时间对扩展方法的思考,写成一个系列文章.每个文章只介绍一个应用方面,篇幅不 ...
- c# 扩展方法奇思妙用集锦
本文转载:http://www.cnblogs.com/ldp615/archive/2009/08/07/1541404.html 其中本人觉得很经典的:c# 扩展方法奇思妙用基础篇五:Dictio ...
- EF OrderBy(string propertyname), OrderByDescending(string propertyname) 按属性排序,扩展方法
public static class LinqExtensions { private static PropertyInfo GetPropertyInfo(Type objType, strin ...
- C# 扩展方法集
语法注意点 可以使用扩展方法来扩展类或接口. 不能重写扩展方法. 扩展方法只能在非嵌套.非泛型静态类内部定义. 扩展方法必须定义在静态类中. 扩展方法的第一个参数的类型用于指定被扩展的类型,它限制该扩 ...
随机推荐
- hdu 4742 Pinball Game 3D(三维LIS&cdq分治&BIT维护最值)
Pinball Game 3D Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- Maven--要点笔记
--maven笔记 1.maven命令 2.archetype插件:用于创建符合maven规定的文件夹骨架 命令: mvn archetype:generate 3. 坐标:构件 仓库: 本地仓库 ...
- c#:无法将 NULL 转换成“System.DateTime”,因为它是一种值类型(转)
摘自:http://www.blogjava.net/parable-myth/archive/2010/09/30/333454.html 在C# 2.0里面的数据类型中,分为值类型和引用类型,引用 ...
- Hive面试题——累计求和
需求: 有如下访客访问次数统计表 t_access_times 访客 月份 访问次数 A 2015-01 5 A 2015-01 15 B 2015-01 5 A 2015-01 8 B 2015-0 ...
- 基于Redis的消息队列php-resque
转载:http://netstu.5iunix.net/archives/201305-835/ 最近的做一个短信群发的项目,需要用到消息队列.因此开始了我对消息队列选型的漫长路. 为什么选型会纠结呢 ...
- C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式
C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...
- 数据流图(DFD)画法
数据流图(DFD)画法要求 一.数据流图(DFD) 1.数据流图的基本符号 数据流图由四种基本符号组成,见图5-4-1所示. 图5-4-1 数据流图的基本符号 例:图5-4-2是一个简单的数据流图, ...
- linux命令汇总1
允许非root用户使用“sudo” root身份登录系统,执行“visudo”,根据示例添加新的一个规则(记住输入的密码是当前用户密码,而不是root密码)#不需要密码执行sudo命令hadoop ...
- Ubuntu14.04.3 64位环境下openjdk7编译
系统环境:Ubuntu14.04.3 -amd64 in VMWare1.安装openjdk7依赖 sudo apt- sudo apt--jdk sudo apt-get install build ...
- 452. Remove Linked List Elements【Naive】
Remove all elements from a linked list of integers that have value val. Example Given 1->2->3- ...