65.9K
CodeProject 正在变化。 阅读更多。
Home

为您的业务对象集合提供简单通用的排序技术

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.07/5 (9投票s)

2005年8月20日

1分钟阅读

viewsIcon

71039

downloadIcon

134

本文讨论了基于业务实体中的任何属性对用户定义的集合对象进行排序的方法。

引言

停止编写 IComparer 类来排序您的自定义集合!本文讨论了基于业务实体中的任何属性对用户定义的集合对象进行排序的方法。此排序技术适用于所有集合对象。您可以根据它们的属性对集合进行排序。

场景

例如,考虑“Student”和“StudentCollection”类

public class Student
 {
     string name="";
     public string Name
     {
         get{return name;}
         set{name = value;}
     }
     int id=0;
     public int Id
     {
         get{return id;}
         set{id = value;}
     }
     DateTime dob=DateTime.MinValue;
     public DateTime DOB
     {
         get{return dob;}
         set{dob = value;}
     }
     public Student(string name,int id,DateTime Dob)
    {
         this.name = name;
         this.id = id;
         this.dob = Dob;
    }
 }
 public class StudentCollection : CollectionBase
 {
     public StudentCollection()
     {
     } 
     //Other code ……..
     // ...
 }

Student 集合由 Student 对象集合组成。Student 实体包含三个属性,即 name(姓名)、id(ID)和 Dob(出生日期)。如果您想根据学生的姓名、ID 或出生日期对集合进行排序,则需要为每个用户定义的集合编写 Comparer 类,如下所示。

使用 IComparer 和 IComparable 接口的常规对象排序方法

class StudentComparer : IComparer
{
    private int intCompType;
    public StudentComparer (int sortOrder)
    {
        intCompType = sortOrder;
    }
    public int Compare(object x,object y)
    {
        switch(intCompType)
        {
            case (int)enuSortOrder.NameAsc:
                return ((Student)x).Name.CompareTo(((Student)y).Name);
            case (int)enuSortOrder.NameDesc:
                return ((Student)y).Name.CompareTo(((Student)x).Name);
        }
    }
}

问题

对于 StudentCollection,我们需要一个 StudentComparer 类,对于 ProductCollection,我们需要一个 ProductComparer 类……依此类推。为了避免这些繁琐的编码,我编写了一个通用的“SortableCollectionBase”类,它可以用于对任何自定义集合对象进行排序,而无需进行繁琐的编码。

解决方案

它是如何工作的?

SortableCollectionBase 类使用“GenericComparer”类进行排序。“GenericComparer”类实现了 IComparer 接口,并动态地根据类类型的 public 属性(排序列)比较对象,而与集合无关。

GenericComparer 类

/// <summary>
/// This class is used to compare any 
/// type(property) of a class.
/// This class automatically fetches the 
/// type of the property and compares.
/// </summary>
public sealed class GenericComparer:IGenericComparer 
{
    /// <summary>
    /// Sorting order
    /// </summary>
    public enum SortOrder
    {
        Ascending = 0,
        Descending = 1
    }
    Type objectType;
    /// <summary>
    /// Type of the object to be compared.
    /// </summary>
    public Type ObjectType
    {
        get{return objectType;}set{objectType = value;}
    }
    string sortcolumn = "";
    /// <summary>
    /// Column(public property of the class) to be sorted.
    /// </summary>
    public string SortColumn
    {
        get{return sortcolumn;}set{sortcolumn = value;}
    }
    int sortingOrder = 0;
    /// <summary>
    /// Sorting order.
    /// </summary>
    public int SortingOrder
    {
        get{return sortingOrder;}set{sortingOrder = value;}
    }
    /// <summary>
    /// Compare interface implementation
    /// </summary>
    /// <param name="x">Object 1</param>
    /// <param name="y">Object 2</param>
    /// <returns>Result of comparison</returns>
    public int Compare(object x, object y)
    {
        //Dynamically get the protery info 
        //based on the protery name
        PropertyInfo propertyInfo = 
              ObjectType.GetProperty(sortcolumn);
        //Get the value of the instance
        IComparable obj1 = 
              (IComparable)propertyInfo.GetValue(x,null) ;
        IComparable obj2 = 
              (IComparable)propertyInfo.GetValue(y,null) ;
        //Compare based on the sorting order.
        if(sortingOrder == 0)
        return ( obj1.CompareTo(obj2) );
        else
        return ( obj2.CompareTo(obj1) );
    }
}

SortableCollectionBase 类

/// <summary>
/// Abstract implementation of Sortable collection.
/// </summary>
public abstract class SortableCollectionBase : 
                            CollectionBase,ISortable
{
    string sortcolumn="";
    public string SortColumn
    {
        get{return sortcolumn;}
        set{sortcolumn = value;}
    }
    GenericComparer.SortOrder sortingOrder = 
              GenericComparer.SortOrder.Ascending;
    public GenericComparer.SortOrder SortingOrder
    {
        get{return sortingOrder;}set{sortingOrder = value;}
    }
    Type sortObjectType;
    public Type SortObjectType
    {
        get{return sortObjectType;} set{sortObjectType = value;} 
    }
    public virtual void Sort() 
    {
        if(sortcolumn == "") 
            throw new Exception("Sort column required."); 
        if(SortObjectType == null) 
            throw new Exception("Sort object type required."); 
        IGenericComparer sorter = new GenericComparer();
        sorter.ObjectType = sortObjectType;
        sorter.SortColumn = sortcolumn;
        sorter.SortingOrder = (int)sortingOrder;
        InnerList.Sort(sorter);
    }
}

如何使用 SortableCollectionBase 类?

使用 SortableCollectionBase 简单而轻松。只需从 SortableCollectionBase 类继承您的自定义集合类,并在构造函数中设置 SortableObjectType 属性。现在您的类就可排序了。

例如

/// <summary>
/// Note : This student collection 
/// inherhits SortableCollectionBase
/// In the constructor set the 
/// SortObjectType for sorting.
/// </summary>
public class StudentCollection : 
                      SortableCollectionBase
{
    public StudentCollection()
    {
        //In your collection class 
        //constructor add this line.
        //set the SortObjectType for sorting.
        base.SortObjectType = typeof(Student);
    }
    public Student this[ int index ] 
    {
        get 
        {
            return( (Student) List[index] );
        }
        set 
        {
            List[index] = value;
        }
    }
    public int Add( Student value ) 
    {
        return( List.Add( value ) );
    }
    public int IndexOf( Student value ) 
    {
        return( List.IndexOf( value ) );
    }
    public void Insert( int index, Student value ) 
    {
        List.Insert( index, value );
    }
    //......
}

如何排序?

要对您的自定义集合进行排序,请调用“Sort()”方法。注意:在调用“Sort()”方法之前,请确保已设置“SortColumn”属性。“SortColumn”是业务实体的一个属性,集合将基于该属性进行排序。在这种情况下,SortColumn 可以是“name”、“id”或“Dob”。

StudentCollection Students = new StudentCollection();
Students.Add(new Student("Sai",5,new DateTime(1914,10,4)));
Students.Add(new Student("Sree",1,new DateTime(1980,10,4)));
Students.Add(new Student("Sow",3,new DateTime(2000,4,1)));
Students.Add(new Student("Zaheer",2,new DateTime(1978,1,27)));
Students.SortColumn = "Name";
Students.SortingOrder = 
     GenericComparer.SortOrder.Ascending;
Students.Sort();
dataGrid1.DataSource = Students;
© . All rights reserved.