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# 扩展方法集
语法注意点 可以使用扩展方法来扩展类或接口. 不能重写扩展方法. 扩展方法只能在非嵌套.非泛型静态类内部定义. 扩展方法必须定义在静态类中. 扩展方法的第一个参数的类型用于指定被扩展的类型,它限制该扩 ...
随机推荐
- 解析theme()
drupal_render()只是对theme()的调用做了包装,真正做任务的还是theme(). function theme($hook, $variables = array()) { ... ...
- python --curl重定向到文件范例
import sys import os import subprocess import time start = time.time() old=sys.stdout f=open('test ...
- WinForm下的键盘事件(KeyPress、KeyDown)及如何处理不响应键盘事件
KeyDown事件用来处理功能键:F1 F2 F3... keyPress事件用来处理字符比如说:A B C... 1 2 3... 注:处理该事件时,需要先将窗体的 KeyPreview=true; ...
- fatfs文件系统f_lseek追加文件
http://home.eeworld.com.cn/my/space-uid-430378-blogid-74720.html 这个时候我以为读出的数据应该是stm32f107学习!!!文件系统学习 ...
- C# 获取文件MD5、SHA1
/// <summary> /// 计算文件的 MD5 值 /// </summary> /// <param name="fileName"> ...
- C#中将图片转化成base64字符串
厂址:http://www.cnblogs.com/yunfeifei/p/4165351.html 1.在C#中将图片转化成base64字符串: using System; using System ...
- Spring Cloud(一):概述以及核心成员介绍
什么是Spring Cloud? Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全 ...
- Atitit. 悬浮窗口的实现 java swing c# .net c++ js html 的实现
Atitit. 悬浮窗口的实现 java swing c# .net c++ js html 的实现 1. 建立悬浮窗口引用代码 1 1.1. 定义悬浮窗口,设置this主窗口引用,是为了在悬浮窗口中 ...
- [svc]salt基本原理
转载自:来自:http://tech.mainwise.cn/?p=438 说明:salt是一个异构平台基础设置管理工具(虽然我们通常只用在Linux上),使用轻量级的通讯器ZMQ,用Python写成 ...
- JMeter学习笔记(四)
1. 断言 断言组件是通过获取服务器响应数据,然后根据断言规则去匹配这些响应数据:匹配到是正常现象,此时我们看不到任何提醒,如果匹配不到,即出现了异常情况,此时JMeter就会断定这个事务失败,那么我 ...