I have blogged at one time on an IComparer class that you could use to sort a property in an object within a collection http://www.jamesandchey.net/?p=601.
The downside was that the name of the object was hard-coded in the IComparer class. If I needed to sort different objects, I would have to create multiple IComparer classes. Well, that’s no good!
I was now on the hunt for one IComparer class that was generic in nature so I can sort multiple collections calling just the one IComparer class.
Here is a generic IComparer class written in visual basic. After the class, I demonstrate how to call the class.
Imports System.Collections.Generic Imports System.Text Imports System.Reflection Public Class GenericIComparer(Of T) Implements IComparer(Of T) Private m_memberName As String = String.Empty Private m_sortOrder As String = String.Empty Private m_methodParameters As New List(Of Object)() Private propertyInfo As PropertyInfo = Nothing Private methodInfo As MethodInfo = Nothing Public Property MemberName() As String Get Return m_memberName End Get Set(ByVal value As String) m_memberName = value GetReflected() End Set End Property Public Property SortOrder() As String Get Return m_sortOrder End Get Set(ByVal value As String) m_sortOrder = value End Set End Property Public ReadOnly Property MethodParameters() As List(Of Object) Get Return m_methodParameters End Get End Property Public Sub New() End Sub Public Sub New(ByVal memberName As String, ByVal sortOrder As String, ByVal methodParameters As List(Of Object)) Me.m_memberName = memberName Me.m_sortOrder = sortOrder Me.m_methodParameters = methodParameters GetReflected() End Sub Private Sub GetReflected() Dim underlyingTypes As Type() = Me.[GetType]().GetGenericArguments() Dim thisUnderlyingtype As Type = underlyingTypes(0) Dim mi As MemberInfo() = thisUnderlyingtype.GetMember(m_memberName) If mi.Length > 0 Then If mi(0).MemberType = MemberTypes.[Property] Then propertyInfo = thisUnderlyingtype.GetProperty(m_memberName) ElseIf mi(0).MemberType = MemberTypes.Method Then Dim signatureTypes As Type() = New Type(-1) {} If m_methodParameters IsNot Nothing AndAlso m_methodParameters.Count > 0 Then signatureTypes = New Type(m_methodParameters.Count - 1) {} For i As Integer = 0 To m_methodParameters.Count - 1 signatureTypes(i) = m_methodParameters(i).[GetType]() Next methodInfo = thisUnderlyingtype.GetMethod(m_memberName, signatureTypes) Else methodInfo = thisUnderlyingtype.GetMethod(m_memberName, signatureTypes) End If Else Throw New Exception("Member name: " & m_memberName & " is not a Public Property or " & "a Public Method in Type: " & thisUnderlyingtype.Name & ".") End If Else Throw New Exception("Member name: " & m_memberName & " not found.") End If End Sub Private Function GetComparable(ByVal obj As T) As IComparable If methodInfo IsNot Nothing Then Return DirectCast(methodInfo.Invoke(obj, m_methodParameters.ToArray()), IComparable) Else Return DirectCast(propertyInfo.GetValue(obj, Nothing), IComparable) End If End Function Public Function Compare(ByVal objOne As T, ByVal objTwo As T) As Integer Implements IComparer(Of T).Compare Dim iComparable1 As IComparable = GetComparable(objOne) Dim iComparable2 As IComparable = GetComparable(objTwo) If m_sortOrder IsNot Nothing AndAlso m_sortOrder.ToUpper().Equals("ASC") Then Return iComparable1.CompareTo(iComparable2) Else Return iComparable2.CompareTo(iComparable1) End If End Function End Class
Here is how to call the class:
'Sort the Collection by entered_date Dim _IComparer As New GenericIComparer(Of _MyObject) _IComparer.MemberName = "entered_date" _IComparer.SortOrder = "asc" _MyCollection.Sort(_IComparer)
1) I instantiate the GenericIComparer class.
2) I set the MemberName property to the object property (_MyObject) I want to sort on.
3) I set the SorOrder property to the direction I want to sort.
4) I then call the Sort method.
Note: _MyCollection happens to be defined as a List of (_MyObject). In other words, _MyCollection contains a collection of _MyObject’s. Each object has a property called ‘entered_date’. I simply want to sort the collection and put the objects in order (whether ascending or descending) by ‘entered_date’.