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

排序通用集合

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (7投票s)

2008 年 4 月 9 日

CPOL

2分钟阅读

viewsIcon

46154

downloadIcon

293

本文介绍了如何对通用集合进行排序

引言

在本文中,我将讨论如何使用反射来排序泛型集合。如果使用代码中不存在的类型,则需要修改此代码。此外,如果您想基于类型不是基本类型(整数、字符串等)的变量进行排序,则需要修改代码。此代码只是为您提供排序集合的基本理解,但您需要对其进行修改以满足您的需求。

背景

.NET 2.0 的一大优势是集合和泛型。现在我们可以将对象列表绑定到网格、下拉列表等。在数据集世界中,我们可以使用 DataTable 或 DataView 的 sort 方法来排序结果。集合也提供了相同的选项。本文将讨论如何进行泛型集合排序。

使用代码

以下代码显示了泛型集合排序器

Imports System.Reflection

Namespace CollectionSorter
    Public Class CollectionSorter(Of T)
        Implements IComparer(Of T)

#Region "Private Variables"
        Private _sortColumn As String
        Private _reverse As Boolean
#End Region
        
#Region "Constructor"
        Public Sub New(ByVal sortEx As String)
            'find if we want to sort asc or desc
            If Not String.IsNullOrEmpty(sortEx) Then
                _reverse = sortEx.ToLowerInvariant().EndsWith(" desc")

                If _reverse Then
                    _sortColumn = sortEx.Substring(0, sortEx.Length - 5)
                Else
                    If sortEx.ToLowerInvariant().EndsWith(" asc") Then
                        _sortColumn = sortEx.Substring(0, sortEx.Length - 4)
                    Else
                        _sortColumn = sortEx
                    End If
                End If

            End If
        End Sub
#End Region

#Region "Interface Implementation"

        Public Function Compare(ByVal x As T,
            ByVal y As T) As Integer Implements System.Collections.Generic.IComparer(
            Of T).Compare
            'get the properties of the objects
            Dim propsx() As PropertyInfo = x.GetType().GetProperties(
         System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.Public)
            Dim propsy() As PropertyInfo = x.GetType().GetProperties(
         System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.Public)
            Dim retval As Integer

            'find the column we want to sort based on
            For i As Integer = 0 To propsx.Length - 1
                If _sortColumn.ToLower() = propsx(i).Name.ToLower() Then
                    'find the type of column so we know how to sort
                    Select Case propsx(i).PropertyType.Name
                        Case "String"
                            retval = CStr(propsx(i).GetValue(x, Nothing)).CompareTo(
                                CStr(propsy(i).GetValue(y, Nothing)))
                        Case "Integer"
                            retval = CInt(propsx(i).GetValue(x, Nothing)).CompareTo(
                                CInt(propsy(i).GetValue(y, Nothing)))
                        Case "Int32"
                            retval = CInt(propsx(i).GetValue(x, Nothing)).CompareTo(
                                CInt(propsy(i).GetValue(y, Nothing)))
                        Case "Int16"
                            retval = CInt(propsx(i).GetValue(x, Nothing)).CompareTo(
                                CInt(propsy(i).GetValue(y, Nothing)))
                        Case "DateTime"
                            retval = CDate(propsx(i).GetValue(x, Nothing)).CompareTo(
                                CDate(propsy(i).GetValue(y, Nothing)))
                    End Select

                End If
            Next

            If _reverse Then
                Return -1 * retval
            Else
                Return retval
            End If

        End Function
#End Region

#Region "Equal Function"

        Public Function Equals(ByVal x As T, ByVal y As T) As Boolean
            Dim propsx() As PropertyInfo = x.GetType().GetProperties(
         System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.Public)
            Dim propsy() As PropertyInfo = y.GetType().GetProperties(
         System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.Public)
            Dim retval As Boolean
            For i As Integer = 0 To propsx.Length - 1
                If _sortColumn.ToLower() = propsx(i).Name.ToLower() Then
                    retval = propsx(i).GetValue(x, Nothing).Equals(propsy(i).GetValue(y,
                        Nothing))
                End If
            Next
            Return retval
        End Function
#End Region

    End Class
End Namespace
        

首先,该类应继承自 IComparer(Of T) 接口。此接口只有一个方法。需要实现的方法是
Public Function Compare(ByVal x As T, ByVal y As T) As Integer
基本上,此方法比较两个类型为T的对象。让我们退一步,在类的构造函数中,我们将获得排序表达式,例如,如果我们有一个名为“Title”的属性的对象 book,并且想基于标题进行排序,我们应该使用类似于“Title asc”或“Title desc”的表达式。在 compare 函数中,我们将使用反射器找到要排序的列,然后我使用反射器获取列的类型,然后我使用该类型的 compare 方法来比较值。

我实现的另一个函数是 Equal

以下代码显示了如何使用泛型集合排序器

Dim BookList As List(Of Book) = New List(Of Book)
        Dim m_book As Book
        m_book = New Book()
        m_book.Author = "Bill Gates"
        m_book.Title = "How to get rich as software engineer!"
        m_book.PublishDate = "1/1/2000"

        BookList.Add(m_book)
        m_book = New Book()
        m_book.Author = "Steve Job"
        m_book.Title = "Why apple went down the drain!"
        m_book.PublishDate = "1/1/2007"
        BookList.Add(m_book)

        Dim colsorter As CollectionSorter(Of Book) = New CollectionSorter(Of Book)(
            "Author asc")
        BookList.Sort(colsorter)

关注点

为了改进此代码,您可以让用户能够基于多个列(属性)进行排序。

© . All rights reserved.