I am trying to dynamically create an expression tree to change the sort order for the data contained in a dictionary of dictionaries. There is a lot of information about dynamically defining a column for sorting, but this is actually not the part that I'm having problems with. I am struggling with a MethodCallExpression that builds my expression tree.
In this example, I have simplified the dictionary:
Dictionary<string, Dictionary<int, int>> data = new Dictionary<string, Dictionary<int, int>>();
I am trying to create an expression that would be equivalent to something like this:
data.OrderByDescending(someValue) .ThenByDescending(someothervalue) .ThenByDescending(anothervalue)...etc
Where the number of ThenBy or ThenByDescending offers at runtime is indicated.
Let's say that one example needs to be sorted by the keys 4, then 3, then 1. I have established (I think) that the following expressions translate into my 3 sort orders:
Expression<Func<KeyValuePair<string, Dictionary<int, int>>, int>> ex1 = (r => r.Value[4]); Expression<Func<KeyValuePair<string, Dictionary<int, int>>, int>> ex2 = (r => r.Value[3]); Expression<Func<KeyValuePair<string, Dictionary<int, int>>, int>> ex2 = (r => r.Value[1]);
So, at compile time, I can write this expression and it works fine:
var sortedResults = dic.OrderByDescending(ex1.Compile()).ThenByDescending(ex2.Compile()).ThenByDescending(ex3.Compile());
However, since the number of sort expressions will change at runtime, I need to build this dynamically, which I'm afraid of. I know that query expressions can be created at runtime using the MethodCallExpression method. An MSDN example shows this:
// ***** OrderBy(company => company) ***** // Create an expression tree that represents the expression // 'whereCallExpression.OrderBy(company => company)' MethodCallExpression orderByCallExpression = Expression.Call( typeof(Queryable), "OrderBy", new Type[] { queryableData.ElementType, queryableData.ElementType }, whereCallExpression, Expression.Lambda<Func<string, string>>(pe, new ParameterExpression[] { pe })); // ***** End OrderBy *****
However, I just can't make the transition from this example to a dictionary of dictionaries that uses this:
Func<KeyValuePair<string, Dictionary<int, int>>, int>
It seems to me that I need to write something like this (this is in partial psuedo code):
private static void Test() { var query = data.AsQueryable() foreach (int key in ListOfRequiredKeys) { Expression<Func<KeyValuePair<string, Dictionary<int, int>>, int>> exp = (r => r.Value[key]); MakeQuery(exp, query); } } private static IQueryable MakeQuery(Expression<Func<KeyValuePair<string, Dictionary<int, int>> exp, IQueryable query) { MethodCallExpression orderByCallExpression = Expression.Call( typeof(Queryable), "ThenBy", new Type[] { query.ElementType, query.ElementType }, query.Expression, Expression.Lambda<Expression<Func<KeyValuePair<string, Dictionary<int, int>>>(exp)); }
I know that this is not the correct syntax, but it should indicate my thinking. Can anyone advise how to switch from the MSDN example, dynamically sort this dictionary of dictionaries?
thanks
Jason