linq中的动态排序

请考虑这种情况:

我有一个包含大约50个字段的类的列表。我想要一个用户可以根据字段列表进行排序的Combobox。例如,如果用户选择“F1”列表,则根据“F1”排序。

我不想为每个字段使用if-else排序。我看到这个主题:

在对数据集或对象列表进行数据绑定时对网格视图进行排序

但我无法使用它的答案。 我如何才能将Expression Tree用于此目的?

谢谢

编辑1)

据亲爱的@Thom Smith回答,我写了这段代码:

  using (NorthwindModel1.NorthwindEntities2 ent = new NorthwindModel1.NorthwindEntities2()) { var query = from o in ent.Orders where o.OrderID < 10257 select o; query.OrderBy("CustomerID", SortDirection.Ascending); GridView1.DataSource = query; GridView1.DataBind(); } 

但它没有排序。 如果我用这种方式编写代码:

 GridView1.DataSource = query.OrderBy(o=>o.CustomerID); 

它是排序的。 问题出在哪儿?

OrderBy不进行就地排序。 它返回一个序列, 在评估时将对其进行排序。 这通常是懒惰地进行的,这意味着:直到它被枚举,它什么都不做 。 您当前的代码只会丢弃这个非常重要的返回值。 修复很简单:捕获返回值:

 query = query.OrderBy("CustomerID", SortDirection.Ascending); 

注意:类似地,应用“Where”不会过滤现有数据:它返回枚举时过滤的序列。 所以,如果你过滤你有类似的:

 query = query.Where(...); 

这是我用于此的方法:

 private IQueryable OrderQuery(IQueryable query, OrderParameter orderBy) { string orderMethodName = orderBy.Direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending"; Type t = typeof(T); var param = Expression.Parameter(t, "shipment"); var property = t.GetProperty(orderBy.Attribute); /* We can't just call OrderBy[Descending] with an Expression * parameter because the second type argument to OrderBy is not * known at compile-time. */ return query.Provider.CreateQuery( Expression.Call( typeof(Queryable), orderMethodName, new Type[] { t, property.PropertyType }, query.Expression, Expression.Quote( Expression.Lambda( Expression.Property(param, property), param)) )); } 

OrderParameter只是一个具有属性和方向的结构。

编辑:补充说明。

此方法来自我的DynamicOrderList类,它是OrderParameter对象的列表。 如果您只需要按一个字段排序,那么您可以稍微简化一下:

 private IQueryable OrderByDynamic(this IQueryable query, string attribute, SortDirection direction) { try { string orderMethodName = direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending"; Type t = typeof(T); var param = Expression.Parameter(t); var property = t.GetProperty(attribute); return query.Provider.CreateQuery( Expression.Call( typeof(Queryable), orderMethodName, new Type[] { t, property.PropertyType }, query.Expression, Expression.Quote( Expression.Lambda( Expression.Property(param, property), param)) )); } catch (Exception) // Probably invalid input, you can catch specifics if you want { return query; // Return unsorted query } } 

然后使用它像:

 myQuery = myQuery.OrderByDynamic("name", SortDirection.Ascending); 

编辑2:

 public IQueryable OrderBy(this IQueryable query, string attribute, SortDirection direction) { return ApplyOrdering(query, attribute, direction, "OrderBy"); } public IQueryable ThenBy(this IQueryable query, string attribute, SortDirection direction) { return ApplyOrdering(query, attribute, direction, "ThenBy"); } private IQueryable ApplyOrdering(IQueryable query, string attribute, SortDirection direction, string orderMethodName) { try { if (direction == SortDirection.Descending) orderMethodName += "Descending"; Type t = typeof(T); var param = Expression.Parameter(t); var property = t.GetProperty(attribute); return query.Provider.CreateQuery( Expression.Call( typeof(Queryable), orderMethodName, new Type[] { t, property.PropertyType }, query.Expression, Expression.Quote( Expression.Lambda( Expression.Property(param, property), param)) )); } catch (Exception) // Probably invalid input, you can catch specifics if you want { return query; // Return unsorted query } } 

和:

 myQuery=myQuery.OrderBy("name", SortDirection.Ascending).ThenBy("date", SortDirection.Descending); 

查看此链接使用Linq按字段名称进行多字段排序

希望它可能有助于实现您的需求。

这是我的热门Enumerable ,使用Enumerable + Reflection代替查询:

 list.OrderBy(x => { var prop = x.GetType().GetProperty(sortFieldName); return prop.GetValue(x); }); if (!isSortAsc) list.Reverse(); 

希望它会有所帮助。 它适用于我动态过滤C#List

 string jtSorting = "ContactName"; DashboardModel Sup = new DashboardModel(); List lstSup = Sup.GetonBoard(); lstSup = lstSup.AsQueryable().SortBy(jtSorting).ToList();