In the past week, I created some CodeSmith templates for my client so we could quickly generate the business objects for our web site. Since the project will be VS2008, I decided to bing objects to List<T> collections of objects, so I could start leveraging LINQ to Objects in the code.
They wanted every field in the GridView sortable, and I always looks for an reusable way to do things when possible. Since we were going to have many, many grids, this was a great opportunity to use generics and LINQ to come up with a flexible solution.
In this case, I wanted a way of taking in a field name, and sort direction, and sorting the collection. It was easy to do using a Lambda expression if I knew in advance all the field names, such as MyCollection.OrderBy(a => a.Name) to sort by name. Obviously, that wasn't going to work. I needed to create a delegate for sorting on the right field dynamically.
Below is the result of that effort. By using the Lambda.Expression (provided by System.Core.dll), I was able to dynamically set the Lambda expression to the property I wanted. Depending on the direction, I used OrderBy or OrderByDescending with the dynamic sort expression. I created it as an extension method to all List<T> objects for quick and easy access, which every business object in my solution supports.
/// <summary>
/// Sorts a list of objects by passing in the parameter and direction.
/// Usage: List<MyObject> newList = oldList.SortList("SomeColumn", "SomeDirection");
/// Requires System.Core be included in the project.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list">The list.</param>
/// <param name="sortColumn">The sort column.</param>
/// <param name="direction">The direction.</param>
/// <returns></returns>
public static List<T> SortList<T>(this List<T> list, string sortColumn, string direction)
{
var param = Expression.Parameter(typeof(AutoClassParams), sortColumn);
var sortExpression = Expression.Lambda<Func<T, object>>(Expression.Convert(Expression.Property(param, sortColumn), typeof(object)), param);
List<T> newList = null;
if (direction.ToUpper() == "ASC")
newList = list.AsQueryable<T>().OrderBy(sortExpression).ToList<T>();
else
newList = list.AsQueryable<T>().OrderByDescending(sortExpression).ToList<T>();
return newList;
}