GenericComparer<T>
Use when sorting Lists: people.Sort(new GenericComparer<Person>("DateOfBirth"));
In .Net 3.5+, simply use the Linq extensions: people.OrderBy(x => x.DateOfBirth);
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Library.Data
{
/// <summary>
/// A generic comparer for List<T>.Sort(IComparer).
/// For strings, use <see cref="System.StringComparer"/>
/// </summary>
public class GenericComparer<T> : IComparer<T>
{
private readonly MethodBase methodInfo; //cache the method
private readonly bool descending;
/// <summary>
/// Initializes a new instance of the <see cref="GenericComparer<T>"/> class with ascending sort.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
public GenericComparer(string propertyName)
: this(propertyName, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericComparer<T>"/> class specifying sort direction
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <param name="descending">if set to <c>true</c> descending.</param>
public GenericComparer(string propertyName, bool descending)
{
methodInfo = typeof(T).GetProperty(propertyName).GetGetMethod();
this.descending = descending;
}
#region IComparer<T> Members
/// <summary>
/// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
/// </summary>
public int Compare(T x, T y)
{
int result = 0;
if (x == null)
result = -1;
else if (y == null)
result = 1;
else
result = CompareValue(
methodInfo.Invoke(x, null),
methodInfo.Invoke(y, null));
if (descending) result = -result;
return result;
}
/// <summary>
/// Compares the value using <see cref="IComparable"/> or ToString()
/// </summary>
private static int CompareValue(object x, object y)
{
//check null values
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
//check comparable
IComparable cx = x as IComparable;
if (cx != null) //they are IComparable
return cx.CompareTo((IComparable)y);
//not comparable, compare ToString
if (!x.Equals(y))
return x.ToString().CompareTo(y.ToString());
return 0;
}
#endregion
}
}