Click here to Skip to main content
13,299,727 members (71,928 online)
Click here to Skip to main content
Add your own
alternative version


16 bookmarked
Posted 10 Apr 2009

Sort IEnumerableT by column name

, 14 Apr 2009
Rate this:
Please Sign up or sign in to vote.
Extension method overload of OrderBy which uses column name instead of lambda.


An in depth discussion of Expression Trees and Extension methods is beyond the scope of this article. There are plenty of sources available to learn about that stuff. You probably should go check them out first. Now, on with it...

There is obviously more than one way to skin a cat. This is no exception I'm sure, but this was a pretty fun way. This is an implementation of an extension method overload of IEnumerable<T>.OrderBy().


I can't, for the life of me, remember why but one day, my UI developer came to me and said something along the lines of, "I need to be able to run OrderBy on this List, but I can't use a lambda to the column name because I don't know it until runtime, and all I will have is a string of the name". I immediately thought of overloading OrderBy() to take a string representing the name of the attribute of the items in the list to order by as opposed to the existing method that takes a lambda. As I began thinking about how to implement it though, the idea started forming to take the string name and somehow generate the lambda which I could then use to defer to the original OrderBy(). It seemed like something that should be possible, and it sounded much more interesting than just writing sort code. How often does a developer get a break from the same old <insert typical backoffice system functionality here>? I hope you enjoy it. I sure enjoyed writing it.

Using the code

Everyone using LINQ is probably familiar with lambdas and most likely using them, or have used them in OrderBy() by now. You might see, for example, sorting a list of products by their price done like this:

var sortedProducts = myProductsList.OrderBy(p => p.Price);

What my UI master wanted was:

var sortedProducts = myProductsList.OrderBy("Price");

And, that's exactly what I gave him. Obviously, I implemented an OrderByDescending() as well.

var sortedProducts = myProductsList.OrderByDescending("Price");

Points of interest

This is the method signature for the extension method for OrderBy().

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector)

As with any extension method, the first parameter represents the object (this) that the method will be called on. It is then of no particular interest to us here. The second parameter is where the lambda signifying which column to sort by goes. That is the guy we want to supplant with our string containing the column name. So, we want:


instead of:

p => p.Price

The first two lines of interest are:

ParameterExpression list = Expression.Parameter(typeof(T), "list");
MemberExpression property = Expression.Property(list, columnName);

The first creates a ParameterExpression (PE) named "list", for lack of something more interesting to call it, based on the type T of which we have an IEnumerable of. The second creates a MemberExpression (ME) on our PE to set up access to the "Price" property (in our example; yours will be whatever you want to sort on). Next, we have a bit of Reflection.

MethodInfo expressionMaker = me.GetMethod("MakeExpression", 
           BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo expressionMethod = 
           expressionMaker.MakeGenericMethod(typeof(T), property.Type);

There's a method included in the source called MakeExpression. We reflect into the containing class in the first call, and get a MethodInfo pointing to it. In the second call, since MakeExpression is a generic method, we have to resolve the generic. Next, we actually call our configured method:

var lambda = expressionMethod.Invoke(null, new object[] { property, list });

At this point, we actually have a lambda which looks like what OrderBy() actually expects; namely:

list => list.Price

We turn this into runnable code by compiling it like so:

var func = (lambda as LambdaExpression).Compile();

Now, a little more Reflection to get a handle on the particular Orderby() that we want to call. I used a little LINQ here for some flair. I'm not convinced this was the best/safest way to do it.

var sortMaker = 
      (from s in enumerable.GetMethods()
          (s.Name == ((IsAscending) ? ASCENDING : DESCENDING))
          && (s.GetParameters().Length == 2) //need a more reliable way to do this
      select s).First();

As before, our method "handle" is for a generic method, so we first need to tell it what the generic will be resolved into before we call it.

MethodInfo sorter = sortMaker.MakeGenericMethod(typeof(T), property.Type);

And now, we defer to it using our concocted lambda:

return sorter.Invoke(source, new object[] { source, func })
              as IOrderedEnumerable<T>;

Don't forget to reference the namespace where you put this class (using foo;) so the extension method will show up.

P.S. Microsoft has a library that does this called Dynamic API, which I promise I did not know about until 6 months after doing this :D


Thanks to Joe for calling me out and forcing me to beef up the explanation.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Troy W Phoenix
Software Developer (Senior)
United States United States
Been designing, implementing, and maintianing projects in .Net since the beginning of time...or so it seems. I've done a little of everything before that though; java, vb classic, c, c++, assembly, pascal, basic.

*I'm not a big fan of UI work.


You may also be interested in...

Comments and Discussions

GeneralDynamic Linq Pin
Partenon12-May-10 3:38
memberPartenon12-May-10 3:38 
GeneralRe: Dynamic Linq Pin
Troy Beacleay12-May-10 4:25
memberTroy Beacleay12-May-10 4:25 
GeneralAvoiding reflection Pin
Richard Deeming15-Apr-09 10:09
memberRichard Deeming15-Apr-09 10:09 
GeneralRe: Avoiding reflection Pin
Troy Beacleay17-Apr-09 11:09
memberTroy Beacleay17-Apr-09 11:09 
GeneralRe: Avoiding reflection Pin
Sacha Barber13-Jan-10 7:05
mvpSacha Barber13-Jan-10 7:05 
Very nice

Sacha Barber
  • Microsoft Visual C# MVP 2008/2009
  • Codeproject MVP 2008/2009
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue

My Blog :

GeneralRe: Avoiding reflection Pin
TweeZz30-Jun-16 3:58
memberTweeZz30-Jun-16 3:58 
GeneralRe: Avoiding reflection Pin
Richard Deeming30-Jun-16 4:01
mvpRichard Deeming30-Jun-16 4:01 
QuestionThe code? Pin
Joe Enos10-Apr-09 6:37
memberJoe Enos10-Apr-09 6:37 
AnswerRe: The code? Pin
Troy Beacleay12-Apr-09 16:52
memberTroy Beacleay12-Apr-09 16:52 
AnswerRe: The code? Pin
Troy Beacleay12-Apr-09 18:01
memberTroy Beacleay12-Apr-09 18:01 
GeneralRe: The code? Pin
Joe Enos12-Apr-09 19:40
memberJoe Enos12-Apr-09 19:40 
GeneralRe: The code? Pin
Troy Beacleay13-Apr-09 4:27
memberTroy Beacleay13-Apr-09 4:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171207.1 | Last Updated 14 Apr 2009
Article Copyright 2009 by Troy W Phoenix
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid