泛型List<T>排序(利用反射)
在最近一个项目中,有需求要对页面中所有的gridview添加排序功能。由于gridview的数据源绑定的是一个集合类List,而不是DataTable,所以无法使用DataView排序功能。另外,不同的gridview显示的是不同的业务数据,为了重用代码只能添加一个泛型方法,使用该方法对数据类型T,按照任意给定的属性进行排序。由于是要按照某个不固定的属性对List内的对象进行排序,所以修改类型T,使之实现IComparable接口,并利用List类的Sort () 方法进行排序是无法满足需求的。但是List类还提供了另一个Sort方法,它接受一个IComparer对象作为参数,在IComparer内可以实现排序的业务逻辑。唯一需要的就是进行排序的属性了,而这个在程序的上下文是已知的。
思路已经有了,但动手写代码前,google了一下相关文章,竟然发现有一段功能类似的代码,唯一不同是该该代码的实现中方法并不是泛型的。但是强大的地方是,代码中对实现的排序支持按照多个属性排序。于是稍加修改,一段强大的支持按照多属性对List进行排序的泛型方法就出炉了。
首先是表示排序属性和排序方向的类SortClass,其中保存了排序的属性和排序的方向。
/// <summary>
/// Class used to hold sort information
/// </summary>
public class SortClass
{
private string _sortProperty; public string SortProperty
{
get { return _sortProperty; }
set { _sortProperty = value; }
}
private SortDirection _sortDirection; public SortDirection SortDirection
{
get { return _sortDirection; }
set { _sortDirection = value; }
} public SortClass(string sortProperty, SortDirection sortDirection)
{
_sortProperty = sortProperty;
_sortDirection = sortDirection;
}
Normal
0
false
false
false
MicrosoftInternetExplorer4
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
有了SortClass后就可以开始实现IComparar接口了。下面是Comparer的代码,它实现了IComparar接口,包含实际的排序功能。从代码中可以看出,Comparer通过递归调用CheckSort方法来首先按照多个属性排序的。
/// <summary>
/// Implementation of IComparer
/// </summary>
public class Comparer<T> : IComparer<T>
{
private List<SortClass> _sortClasses; /// <summary>
/// Collection of sorting criteria
/// </summary>
public List<SortClass> SortClasses
{
get { return _sortClasses; }
} /// <summary>
/// Default Constructor
/// </summary>
public Comparer()
{
_sortClasses = new List<SortClass>();
} /// <summary>
/// Constructor that takes a sorting class collection as param
/// </summary>
/// <param name="sortClass">
/// Collection of sorting criteria
///</param>
public Comparer(List<SortClass> sortClass)
{
_sortClasses = sortClass;
} /// <summary>
/// Constructor
/// </summary>
/// <param name="sortProperty">Property to sort on</param>
/// <param name="sortDirection">Direction to sort</param>
public Comparer(string sortProperty, SortDirection sortDirection)
{
_sortClasses = new List<SortClass>();
_sortClasses.Add(new SortClass(sortProperty, sortDirection));
} /// <summary>
/// Implementation of IComparer interface to compare to object
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public int Compare(T x, T y)
{
if (SortClasses.Count == )
{
return ;
}
return CheckSort(, x, y);
} /// <summary>
/// Recursive function to do sorting
/// </summary>
/// <param name="sortLevel">Current level sorting at</param>
/// <param name="myObject1"></param>
/// <param name="myObject2"></param>
/// <returns></returns>
private int CheckSort(int sortLevel, T myObject1, T myObject2)
{
int returnVal = ;
if (SortClasses.Count - >= sortLevel)
{
object valueOf1 = myObject1.GetType().GetProperty(SortClasses[sortLevel].SortProperty).GetValue(myObject1, null);
object valueOf2 = myObject2.GetType().GetProperty(SortClasses[sortLevel].SortProperty).GetValue(myObject2, null);
if (SortClasses[sortLevel].SortDirection == SortDirection.Ascending)
{
returnVal = ((IComparable)valueOf1).CompareTo((IComparable)valueOf2);
}
else
{
returnVal = ((IComparable)valueOf2).CompareTo((IComparable)valueOf1);
} if (returnVal == )
{
returnVal = CheckSort(sortLevel + , myObject1, myObject2);
}
} return returnVal;
}
}
Normal
0
false
false
false
MicrosoftInternetExplorer4
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
准备工作完成后,就可以开始实现真正强大的泛型排序方法了。ListSorter提供了2个静态方法,一个用来对多个属性排序,另一个为了方便只针对一个属性进行排序的情况。
public class ListSorter
{
public static List<T> SortList<T>(List<T> listToSort, List<string> sortExpression, List<SortDirection> sortDirection)
{
//check parameters
if (sortExpression.Count != sortDirection.Count||sortExpression.Count==||sortDirection.Count==)
{
throw new Exception("Invalid sort arguments!");
} //get myComparer
Comparer<T> myComparer = new Comparer<T>();
for (int i = ; i < sortExpression.Count; i++)
{
SortClass sortClass = new SortClass(sortExpression[i], sortDirection[i]);
myComparer.SortClasses.Add(sortClass);
}
listToSort.Sort(myComparer);
return listToSort;
} public static List<T> SortList<T>(List<T> listToSort, string sortExpression, SortDirection sortDirection)
{
//check parameters
if (sortExpression == null || sortExpression == string.Empty || sortDirection == null)
{
return listToSort;
} Comparer<T> myComparer = new Comparer<T>();
myComparer.SortClasses.Add(new SortClass(sortExpression, sortDirection));
listToSort.Sort(myComparer);
return listToSort;
}
}
Normal
0
false
false
false
MicrosoftInternetExplorer4
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
有了上面的代码,只需简单几行就可以轻松实现对泛型List的排序功能了:
List<Project> projectList=...;
List<Project> sortedProject = ListSorter.SortList(projectList, "Name", SortDirection.Ascending);
出处:http://www.cnblogs.com/dytes/archive/2009/01/06/1370623.html
泛型List<T>排序(利用反射)的更多相关文章
- DataTable转任意类型对象List数组-----工具通用类(利用反射和泛型)
public class ConvertHelper<T> where T : new() { /// <summary> /// 利用反射和泛型 /// </summa ...
- 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)
试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...
- 利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理
利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理 2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论: ...
- Java利用反射排序
前言 Java为我们提供了几种排序得方法,比如Arrays和Collections类,但是前提是数组或者集合中的元素都必须实现Comparable接口,基本的数据类型都已经实现了Comparable接 ...
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- <五>JDBC_利用反射及JDBC元数据编写通用的查询方法
此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...
- 利用反射将Datatable、SqlDataReader转换成List模型
1. DataTable转IList public class DataTableToList<T>whereT :new() { ///<summary> ///利用反射将D ...
- 利用反射及jdbc元数据实现通用的查询方法
---------------------------------------------------------------------------------------------------- ...
- 第十篇 一个利用反射实现的Excel导出
前些天写了个导出Excel的公共类,因为项目中也需要上传Excel,没有利用Office组件,(PS:Office在上传文件时候,Excel进程无法关闭,会导致上传和打开失败)有的说利用Kill把进程 ...
随机推荐
- Python 文件操作综合案例
# 案例 # 文件的复制 # 要求 # 将一个文件, 复制到另外一个副本中 # 步骤分析 # 1. # 只读模式, 打开要复制的文件 import os import shutil path = &q ...
- Asp.net Core, 基于 claims 实现权限验证 - 引导篇
什么是Claims? 这个直接阅读其他大神些的文章吧,解释得更好. 相关文章阅读: http://www.cnblogs.com/JustRun1983/p/4708176.html http://w ...
- CodeIgniter 资料
PHP 论坛: http://codeigniter.org.cn/forums/forum-opensource-1.html 下载 CodeIgniter 项目 的最新软件包(http://www ...
- Hive-开启动态分区
开启动态分区 --开启动态分区 set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict ...
- 谷歌SEO老域名注册完全攻略
老域名有优势,不管在百度和谷歌都是一样的. 我们查看搜索结果就能发现,谷歌里面很多排前十的网站都是N年前的,一零年以后的算是比较新的,很多产品网站域名是零几年,甚至很多排名更好的域名是九几年的. 谷歌 ...
- Linux Wget 命令
Linux wget是一个下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,尤其对于网络管理员,经常要下载一些软件或从远程服务器恢复备份到本地服务器.如果我们使用虚拟主机,处理这样的 ...
- cmake的使用方法
4. CMakeLists.txt剖析4.1 cmake_minimum_required命令 cmake_minimum_required (VERSION 2.6) 规定cmake程序的最低版本. ...
- nrm npm源管理利器
nrm npm源管理利器 nrm是管理npm源的一个利器. 有时候我们用npm install 安装依赖时会非常的慢,是官方自身的npm本来就慢,然后我们会尝试安装淘宝的npm或者cnpm,这些安装切 ...
- 在Window工作区按下鼠标左键拖动窗体
Window.DragMove(): 允许使用在窗口工作区的暴露区域上方按下其鼠标左键的鼠标来拖动窗口.(窗口工作区:除去窗体的title.bottom后的剩余部分空间) 使用该方法时注意:一定要在鼠 ...
- .net操作Oracle数据库步骤及方法
1.首先安装PL/SQL Developer Oracle客户端软件 2.安装Oracle Instant Client(即时客户端) 安装与配置 配置环境变量ORAClE HOME 地址为insta ...