A generic sorter for strongly-typed collections

Late last night I was doing some development work on a website for our investment club. I had a strongly-typed collection of "Stock" objects, and wanted to be able to sort them on any parameter (StockName, SharePrice, Volume, MarketCap, etc..) in either descending or ascending order. I didn't want to have to write a separate comparer for each property. Reflection to the rescue! Below is a GenericSorter class, the use of which allows for the development of a Sort() method on the collection taking as a parameter the name of the property on which to sort.  Smart.

using System;
using System.Collections;
using System.Globalization;
using System.Reflection; 
namespace IanNelson.Utilities
{
    /// <SUMMARY>
    /// A generic sorter, inheriting from IComparer, 
    /// intended to allow for the sorting of
    /// strongly-typed collections on any named public property
    /// which implements IComparable
    /// </SUMMARY>
    public class GenericSorter : IComparer
    {
        string sortPropertyName;
        SortOrder sortOrder;
        public GenericSorter(string sortPropertyName)
        {
            this.sortPropertyName=sortPropertyName;
            this.sortDirection=SortDirection.Ascending;    
                                // default to ascending order

        }
        public GenericSorter(string sortPropertyName, 
                                           SortDirection sortOrder)
        {
            this.sortPropertyName=sortPropertyName;
            this.sortDirection=sortDirection;
        }
        public int Compare(object x, object y)
        {
            // Get the values of the relevant property on the
            //  x and y objects

            object valueOfX = x.GetType().
                 GetProperty(sortPropertyName).GetValue(x,null);
            object valueOfY = y.GetType().
                 GetProperty(sortPropertyName).GetValue(y,null);
            // Do the comparison
            if (sortOrder==SortOrder.Ascending)
            {
             return ((IComparable)valueOfX).CompareTo(valueOfY); 
            }
            else

            {
             return ((IComparable)valueOfY).CompareTo(valueOfX);
            }
        }
    }
    /// 
    /// Enumerator to indicate whether to sort in ascending or
    /// descending order
    /// 
    public enum SortDirection
    {
        Ascending,
        Descending
    }
}

To use this class, within a collection which inherits from System.Collections.CollectionBase, we just need to expose a Sort() method along the lines of:

public void Sort(string sortPropertyName, 
                       SortDirection sortDirection)
{
   InnerList.Sort(new IanNelson.Utilities.GenericSorter(
                             sortPropertyName,sortDirection));
}

Bob's your uncle.

Update [2006-02-27]: The above class is no match for some much more fully-featured code that was anonymously sent to me earlier this month which allows for sorting on multiple properties to arbitrary depth within the domain object model, using a simple SQL-like syntax.  Check it out...

#1  avatar rob on 25 Jul 2005 at 22:40

this is really cool. thanks ian.

#2  avatar Clancy on 30 Aug 2005 at 16:30

Great Googley-moogeley - it works!

The objects I am using are bindable, so sorting using this method for a web based datagrid is REALLY handy!

#3  avatar Paul Mortimer on 20 Jan 2009 at 10:22

Cheers deary

Leave a Comment