泛型List排序(利用反射)

  在最近一个项目中,有需求要对页面中全部的gridview添加排序功能。因为gridview的数据源绑定的是一个集合类List,而不是DataTable,因此没法使用DataView排序功能。另外,不一样的gridview显示的是不一样的业务数据,为了重用代码只能添加一个泛型方法,使用该方法对数据类型T,按照任意给定的属性进行排序。因为是要按照某个不固定的属性对List内的对象进行排序,因此修改类型T,使之实现IComparable接口,并利用List类的Sort () 方法进行排序是没法知足需求的。可是List类还提供了另外一个Sort方法,它接受一个IComparer对象做为参数,在IComparer内能够实现排序的业务逻辑。惟一须要的就是进行排序的属性了,而这个在程序的上下文是已知的。
html

  思路已经有了,但动手写代码前,google了一下相关文章,居然发现有一段功能相似的代码,惟一不一样是该该代码的实现中方法并非泛型的。可是强大的地方是,代码中对实现的排序支持按照多个属性排序。因而稍加修改,一段强大的支持按照多属性对List进行排序的泛型方法就出炉了。
app

  首先是表示排序属性和排序方向的类SortClass,其中保存了排序的属性和排序的方向。google

    /// <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;
        }

  有了SortClass后就能够开始实现IComparar接口了。下面是Comparer的代码,它实现了IComparar接口,包含实际的排序功能。从代码中能够看出,Comparer经过递归调用CheckSort方法来首先按照多个属性排序的。spa

    /// <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 == 0)
            {
                return 0;
            }
            return CheckSort(0, 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 = 0;
            if (SortClasses.Count - 1 >= 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 == 0)
                {
                    returnVal = CheckSort(sortLevel + 1, myObject1, myObject2);
                }
            }


            return returnVal;
        }
    }

  准备工做完成后,就能够开始实现真正强大的泛型排序方法了。ListSorter提供了2个静态方法,一个用来对多个属性排序,另外一个为了方便只针对一个属性进行排序的状况。 code

    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==0||sortDirection.Count==0)
            {
                throw new Exception("Invalid sort arguments!");
            }

            //get myComparer
            Comparer<T> myComparer = new Comparer<T>();
            for (int i = 0; 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;
        }
    }

有了上面的代码,只需简单几行就能够轻松实现对泛型List的排序功能了:orm

    List<Project> projectList=...;
    List<Project> sortedProject = ListSorter.SortList(projectList, "Name", SortDirection.Ascending);

 

 

出处:http://www.cnblogs.com/dytes/archive/2009/01/06/1370623.htmlxml