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...
