我如何根据用户输入在LINQ中使用OrderBy和ThenBy?

我在页面上有一个网格,我希望可以同时在多个列上进行排序。

例如:

UserID FirstName LastName ======================================= 1 Bruce Wayne 2 Peter Parker 3 Clark Kent 4 Tony Stark 5 Helena Wayne 

用户可以选择通过LastName ASC然后通过FirstName DESC进行排序,这将生成以下内容:

 UserID FirstName LastName ======================================= 3 Clark Kent 2 Peter Parker 4 Tony Stark 5 Helena Wayne 1 Bruce Wayne 

用户可以重置订购并决定以其他方式订购。

如何在LINQ中实现这一目标? 据我所知,链式排序的方法是做类似的事情

 superheroes.OrderBy(x => x.LastName).ThenByDescending(x => x.FirstName) 

显然,我不想写出每个可能的列顺序组合(我的网格最多可能有10列)。 有没有办法使订购序列动态化?

您需要使用动态LINQ。 看一下Dynamic LINQ(第1部分:使用LINQ动态查询库)

IEnumerable的一种天真的方法(不完美或测试,但你明白了)。 我把开关放在外面,所以比较只进行一次,而不是每次调用选择器。 有点难看,因为你基本上不得不在OrderBy和ThenBy中重复自己。

 enum OrderableColumns {UserID, FirstName, ...} IOrderedEnumerable OrderBy(SuperHeroes superheroes, OrderableColumns column) { switch(column) { case UserID: return superheroes.OrderBy(x => x.UserID); case FirstName: return superheroes.OrderBy(x => x.FirstName); ... } } IOrderedEnumerable ThenBy(IOrderedEnumerable superheroes, OrderableColumns column) { switch(column) { case UserID: return superheroes.ThenBy(x => x.UserID); case FirstName: return superheroes.ThenBy(x => x.FirstName); ... } } IOrderedEnumerable OrderSuperheroes(SuperHeroes superheroes, params OrderableColumns[] columns) { var ordered = OrderBy(superheroes, columns[0]); foreach(var col in columns.Skip(1)) ordered = ThenBy(ordered, col); return ordered; } 

您可以构建一个Func Dynamic,如下所示:

 public static Func GetExp(string preportyName) { var instance = Expression.Parameter(typeof(T)); var callPreporty = Expression.PropertyOrField(instance, preportyName); var lambda = Expression.Lambda>(callPreporty,instance); return lambda.Compile(); } 

使用这样:

 var pdotName = GetExp("Name"); //equals: p=>p.Name var pdotID = GetExp("Id"); ////equals: p=>p.Id var ordered = list.OrderBy(pdotName).ThenBy(pdotID); //equals: list.OrderBy(p=>p.Name).ThenBy(p=>p.Id)