动态按照属性排序

摘要:
然而,如果一个系统有10个这样的类,并且每个类平均有10个可以选择的属性,这意味着需要编写100个排序方法。如果有一种方法可以直接输入属性的名称,那么基于相应的属性返回比较器会更容易吗?基于该思想并考虑效率,使用Emit使用默认比较器编写简单的单属性排序:Code1publicstaticclassExtensions 2{3publicstaticvoidSortByProperty<T>4{5Array.Sort;6}78publicstaticvoidPortByProperty<T˃9{10list.Sort;11}1213privatestaticassInner<T>14{15privatestaticDictionary<string,Comparison<T>˃m_cache=16newDictionary>string,Comparation<T>(); 1718内部静态比较<T>GetComparison19{20Comparison<T>Comparison;21if(!)在函数方面,由于无法传入比较器,排序函数相对较弱,只能处理属性的默认比较器的排序。

  随着实体的概念的流行,DataTable正在逐渐的淡出我们的视野,但是,有些时候,DataTable很容易做的一件事情,却让我们不得不头痛起来——按指定列排序

  如果数据是来源于一个sql语句,那么,我们可以把这个问题转嫁给sql,让DB来解决这个问题。

  但是,如果数据来源于某些不支持排序(例如webservice并且没有提供排序功能),或者其他复杂情况,这样就不得不依赖于.net的集合排序。可是,如果一个系统有10个这样的类,平均每个类有10个属性可能被选择,那么就意味着有100个排序方法需要被写(c#3.0的Lambda表达式当然可以为我们省下很多力气)。如果,有一个方法直接输入属性的名称,就返回一个按照对应属性的比较器,岂不是更容易?

  基于这个想法,再加上效率的考量,用Emit写了简单的单一属性的使用默认比较器的排序:

动态按照属性排序第1张动态按照属性排序第2张Code
 1动态按照属性排序第3张    public static class Extensions
 2动态按照属性排序第4张动态按照属性排序第5张    动态按照属性排序第6张{
 3动态按照属性排序第7张        public static void SortByProperty<T>(this T[] array, string propName)
 4动态按照属性排序第8张动态按照属性排序第9张        动态按照属性排序第6张{
 5动态按照属性排序第7张            Array.Sort(array, Inner<T>.GetComparison(propName));
 6动态按照属性排序第12张        }

 7动态按照属性排序第7张
 8动态按照属性排序第7张        public static void SortByProperty<T>(this List<T> list, string propName)
 9动态按照属性排序第8张动态按照属性排序第9张        动态按照属性排序第6张{
10动态按照属性排序第7张            list.Sort(Inner<T>.GetComparison(propName));
11动态按照属性排序第12张        }

12动态按照属性排序第7张
13动态按照属性排序第7张        private static class Inner<T>
14动态按照属性排序第8张动态按照属性排序第9张        动态按照属性排序第6张{
15动态按照属性排序第7张            private static Dictionary<string, Comparison<T>> m_cache =
16动态按照属性排序第7张                new Dictionary<string, Comparison<T>>();
17动态按照属性排序第7张
18动态按照属性排序第7张            internal static Comparison<T> GetComparison(string propName)
19动态按照属性排序第8张动态按照属性排序第9张            动态按照属性排序第6张{
20动态按照属性排序第7张                Comparison<T> comparison;
21动态按照属性排序第7张                if (!m_cache.TryGetValue(propName, out comparison))
22动态按照属性排序第7张                    m_cache[propName] = comparison = GetComparisonNoCache(propName);
23动态按照属性排序第7张                return comparison;
24动态按照属性排序第12张            }

25动态按照属性排序第7张
26动态按照属性排序第7张            private static Comparison<T> GetComparisonNoCache(string propName)
27动态按照属性排序第8张动态按照属性排序第9张            动态按照属性排序第6张{
28动态按照属性排序第7张                bool isValueType = typeof(T).IsValueType;
29动态按照属性排序第7张                var prop = typeof(T).GetProperty(propName);
30动态按照属性排序第7张                var comparerType = typeof(Comparer<>).MakeGenericType(prop.PropertyType);
31动态按照属性排序第7张                DynamicMethod dm = new DynamicMethod(string.Empty, typeof(int),
32动态按照属性排序第8张动态按照属性排序第9张                    new Type[] 动态按照属性排序第6张typeof(T), typeof(T) }typeof(T));
33动态按照属性排序第7张                var il = dm.GetILGenerator();
34动态按照属性排序第7张                il.Emit(OpCodes.Call, comparerType.GetProperty("Default").GetGetMethod());
35动态按照属性排序第7张                if (isValueType)
36动态按照属性排序第8张动态按照属性排序第9张                动态按照属性排序第6张{
37动态按照属性排序第7张                    il.Emit(OpCodes.Ldarga_S, 0);
38动态按照属性排序第7张                    il.Emit(OpCodes.Call, prop.GetGetMethod());
39动态按照属性排序第7张                    il.Emit(OpCodes.Ldarga_S, 1);
40动态按照属性排序第7张                    il.Emit(OpCodes.Call, prop.GetGetMethod());
41动态按照属性排序第12张                }

42动态按照属性排序第7张                else
43动态按照属性排序第8张动态按照属性排序第9张                动态按照属性排序第6张{
44动态按照属性排序第7张                    il.Emit(OpCodes.Ldarg_0);
45动态按照属性排序第7张                    il.Emit(OpCodes.Callvirt, prop.GetGetMethod());
46动态按照属性排序第7张                    il.Emit(OpCodes.Ldarg_1);
47动态按照属性排序第7张                    il.Emit(OpCodes.Callvirt, prop.GetGetMethod());
48动态按照属性排序第12张                }

49动态按照属性排序第7张                il.Emit(OpCodes.Callvirt, comparerType.GetMethod("Compare"));
50动态按照属性排序第7张                il.Emit(OpCodes.Ret);
51动态按照属性排序第7张                return (Comparison<T>)dm.CreateDelegate(typeof(Comparison<T>));
52动态按照属性排序第12张            }

53动态按照属性排序第12张        }

54动态按照属性排序第74张    }

55动态按照属性排序第3张

   因为,考虑到经常需要排序可空类型(例如:int?),所以,使用Comparer<T>.Default的Compare方法,当然性能上略有损失,在属性是int的情况下,与直接用Lambda相比,性能大概是5:6,也就是说在数组相对比较大时,如果用Lambda需要5s,那么用这个方法可能就需要6s。功能上来说,由于无法传入比较器,排序功能上比较弱,只能应付用属性的默认比较器的排序的情况。

免责声明:文章转载自《动态按照属性排序》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ssl证书生成与验证开源ckplayer 网页播放器去logo去广告去水印修改下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Django Admin Cookbook-9如何启用对计算字段的排序

9.如何启用对计算字段的排序? 通常,Django会为模型属性字段,自动添加排序功能。当你添加计算字段时,Django不知道如何执行order_by,因此它不会在该字段上添加排序功能。 如果要在计算字段上添加排序,则必须告诉Django需要排序的内容。你可以通过在在计算字段方法中设置admin_order_field属性来执行此操作 。 我们从上一章(如何...

SQL优化(Oracle)

(转)SQL优化原则一、问题的提出  在应用系统开发初期。因为开发数据库数据比較少。对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,可是假设将应用系统提交实际应用后,随着数据库中数据的添加。系统的响应速度就成为眼下系统须要解决的最基本的问题之中的一个。系统优化中一个非常重要的方面就是SQL语句的优化。对于海量数据,劣质SQL...

Mybatis检查SQL注入

Mybatis 的 Mapper.xml 语句中 parameterType 向SQL语句传参有两种方式:#{ } 和 ${ }。 使用#{ }是来防止SQL注入,使用${ }是用来动态拼接参数。 如何排查出 1. 检查是否有$号 如果你使用的是ide代码编辑器,那么可以通过全局搜索${ , 快速定位到使用${ }拼接SQL的语句,在去找到外部传入参数的入...

《深入浅出WPF》学习笔记二数据绑定(Binding)、依赖属性和附加属性

第六章 深入浅出话Binding    1、绑定的源可以是任意对象,并通过属性公开自己的数据;         绑定的目标必须是依赖对象的依赖属性。    2、INotifyPropertyChanged接口,当对象实现了这个接口的时候,当数据源改变的时候可以通知UI同时实现改变,         实现原理:当为Binding设置了数据源后,Bindin...

oracle之数据限定与排序

数据限定与排序6.1 简单查询语句执行顺序from, where, group by, having, order by, selectwhere限定from后面的表或视图,限定的选项只能是表的列或列单行函数或列表达式,where后不可以直接使用分组函数SQL> select empno,job from emp where sal>2000;...

JAVA 使用Comparator接口实现自定义排序

1、原则 Comparator接口可以实现自定义排序,实现Comparator接口时,要重写compare方法: int compare(Object o1, Object o2) 返回一个基本类型的整型 如果要按照升序排序,则o1 小于o2,返回-1(负数),相等返回0,01大于02返回1(正数) 如果要按照降序排序,则o1 小于o2,返回1(正数),相...