我正在尝试动态构建表达式树,以便可以更改包含在字典中的字典数据的排序顺序。有很多关于动态指定要排序的列的信息,但这并不是我遇到问题的部分。我在处理构建表达式树的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排序的一个例子。我已经确定(我认为)以下表达式可以翻译成我的三个排序顺序:
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示例中动态排序这个字典吗?
谢谢
杰森