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# 扩展方法集
语法注意点 可以使用扩展方法来扩展类或接口. 不能重写扩展方法. 扩展方法只能在非嵌套.非泛型静态类内部定义. 扩展方法必须定义在静态类中. 扩展方法的第一个参数的类型用于指定被扩展的类型,它限制该扩 ...
随机推荐
- EMQ学习---客户链接资源消耗
Erlang进程消耗EMQ对客户端链接使用链接进程(emqtt_client)和session进程(emqtt_session)分开的策略. 当一个mqtt的客户端连接到EMQ的服务器上的时候,首先会 ...
- Android 使用Post方式提交数据
在Android中,提供了标准Java接口HttpURLConnection和Apache接口HttpClient,为客户端HTTP编程提供了丰富的支持. 在HTTP通信中使用最多的就是GET和POS ...
- ArcGIS 10 安装程序及破解文件
1.下载 ArcGIS 10 安装程序及破解文件 后面提供电驴的下载地址(可以使用迅雷.QQ旋风等下载工具下载),下载文件是一个光盘镜像文件:ArcGIS_Desktop10_122519.iso. ...
- (一)Mina源代码解析之总体架构
Apache Mina Server 是一个网络通信应用框架.也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然,也能够提供JAVA 对象的序列化服务.虚拟机管道通信服务等).M ...
- Python 列表 list() 方法
描述 Python 列表 list() 方法用于将可迭代对象(字符串.列表.元祖.字典)转换为列表. 注:元组与列表是非常类似的,区别在于元组的元素值不能修改,元组是放在括号中,列表是放于方括号中. ...
- C# Debug
语法.IDE环境使用.Debug方法是学习一门语言的最少必须技能,本文总结C#中的最常用调试方法 一. 断点 如下图所示在欲插入断点的地方右键>断点>插入断点(或在行号左边点击)可在选中语 ...
- Linux下从视频提取音频的方法
Linux下可以利用mencoder将视频里的音频提取出来.方法如下: 1.首先安装mencoder.对于Ubuntu来说,软件仓库里就有mencoder,可直接输入如下命令安装 sudo apt-g ...
- MySQL主从不一致情形与解决方法
参考:https://blog.csdn.net/hardworking0323/article/details/81046408 https://blog.csdn.net/lijingkuan/a ...
- Redis(七):Jedis简介和集群
Jedis简介 1.Jedis 是Redis 客户端工具jar2.使用非集群版示例代码 Jedis jedis = new Jedis("192.168.139.132", 637 ...
- maven optional可选依赖
应用场景:projectA 依赖projectB, projectB 依赖projectC时 <dependency> <groupId>com.itear.projectC ...