Я пытаюсь динамически создать дерево выражений, чтобы изменить порядок сортировки данных, содержащихся в словаре словарей. Существует много информации о динамическом указании столбца для сортировки, но это не та часть, с которой у меня возникают проблемы. Я борюсь с MethodCallExpression , который строит мое дерево выражений.
Для целей этого примера я упростил словарь:
Dictionary<string, Dictionary<int, int>> data = new Dictionary<string, Dictionary<int, int>>();
Я пытаюсь создать выражение, которое будет эквивалентно чему-то вроде этого:
data.OrderByDescending(someValue)
.ThenByDescending(someothervalue)
.ThenByDescending(anothervalue)...etc
Где количество предложений «ThenBy» или «ThenByDescending» определяется во время выполнения.
Допустим, один пример необходим для сортировки по ключам 4, затем 3, затем 1. Я установил (я думаю), что следующие выражения переводятся в мои 3 порядка сортировки:
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]);
Итак, во время компиляции я могу написать это выражение, и оно отлично работает:
var sortedResults = dic.OrderByDescending(ex1.Compile()).ThenByDescending(ex2.Compile()).ThenByDescending(ex3.Compile());
Однако, так как количество выражений сортировки будет меняться во время выполнения, мне нужно построить это динамически, вот где я борюсь.
Мне известно, что выражения запросов могут быть созданы во время выполнения с использованием MethodCallExpression. Пример MSDN показывает это:
// ***** 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 *****
Однако я просто не могу перейти от этого примера к своему словарю словарей, который использует это:
Func<KeyValuePair<string, Dictionary<int, int>>, int>
Я думаю, мне нужно написать что-то вроде этого (это частично псевдо-код):
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));
}
Я знаю, что это неправильный синтаксис, но он должен отражать мое мышление. Кто-нибудь может посоветовать, как перейти от примера MSDN, чтобы динамически сортировать этот словарь словарей?
Спасибо
Jason