Dynamic Linq: OrderBy Using a String for a Property Name

Now this is kind of dangerous to do since there is no compile time check (Like most things set in markup) but say you want to sort a collection, using the Linq extension methods, but you don’t know what you what to sort on at any given time. On top of that, you have a datagrid and a bunch of sort expressions to deal with. Now you could do something like create a hashtable full of lambda expressions that the key is the sort expression:

Dictionary<String, Func<User, IComparable>> list;

userList = User.GetUserList();
list = new Dictionary<String, Func<User, IComparable>>();
list.Add("UserName", currentUser => currentUser.UserName);
list.Add("UserID", currentUser => currentUser.UserID);
userList.OrderBy(list["UserID"]);

Works just fine, and might be preferable to what I’m about to show. OooOoOO sound eerie?

//This is just to get the property info using reflection.  In order to get the value
//from a property dynamically, we need the property info from the class
public static PropertyInfo[] GetInfo<K>(K item) where K : class
{
  PropertyInfo[] propertyList;
  Type typeInfo;

  typeInfo = item.GetType();
  propertyList = typeInfo.GetProperties();

  return propertyList;
}

//This is the dynamic order by func that the OrderBy method needs to work
public static IComparable OrderByProperty<T>(String propertyName, T item)
  where T : class
{
  PropertyInfo[] propertyList;

  propertyList = GetInfo(item);

  //Here we get the value of that property of the passed in item and make sure
  //to type the object (Which is what GetValue returns) into an IComparable
  return (IComparable)propertyList.First(currentProperty
    => currentProperty.Name == propertyName).GetValue(item, null);
}

And use:

//This takes the current user and calls the OrderByProperty method which in turn
//gives us the Func OrderBy is requesting.
var test = userList.OrderBy(currentUser
  => DynamicPropertySort.OrderByProperty("UserID", currentUser)).ToList();

Ok so what the hell? I mean intellisense on the OrderBy method doesn’t give much help. Func<<User, TKey>>. Yeah ok. So basically the return type is open. Well this kind of sucks right? Because I would have to return a Func that already knows the return type. (Be it string, int, ect) Of course, this would mean we would have to handle each sort expression in code. NOT VERY DYNAMIC IS IT? Well f that. Truth is, what the order by is looking for is a Func that takes in a User and returns something it can compare. This is where IComparable comes in.

The OrderBy has to take the returned value, say UserID which is an int, and figure out how to compare it to another value. Pretty simple. So as long as the property you are ordering by uses IComparable, you’re good to go. Pretty nice huh?

Now I would suggest, if you use this (HAHAHAHA), is to cache a dictionary of the property info with the class type as the key so that you don’t have to use as much reflection everytime. I just didn’t put that in.

U U USING

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

5 thoughts on “Dynamic Linq: OrderBy Using a String for a Property Name”

  1. boiled that down a bit:

            private void SortListBy(string prop)
            {
                var orderedList = userList.OrderBy(user => GetComparableValue(prop, user));
            }
           
            public static IComparable GetComparableValue(string propName, T item) where T : class
            {
                return (IComparable)typeof(T).GetProperty(propName).GetValue(item, null);
            }

Comments are closed.