Dynamic LINQ OrderBy on IEnumerable / IQueryabl

2018-12-30 23:49发布

I found an example in the VS2008 Examples for Dynamic LINQ that allows you to use a sql-like string (e.g. OrderBy("Name, Age DESC")) for ordering. Unfortunately, the method included only works on IQueryable<T>;. Is there any way to get this functionality on IEnumerable<T>?

19条回答
还给你的自由
2楼-- · 2018-12-31 00:01

After a lot of searching this worked for me:

public static IEnumerable<TEntity> OrderBy<TEntity>(this IEnumerable<TEntity> source, 
                                                    string orderByProperty, bool desc)
{
    string command = desc ? "OrderByDescending" : "OrderBy";
    var type = typeof(TEntity);
    var property = type.GetProperty(orderByProperty);
    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExpression = Expression.Lambda(propertyAccess, parameter);
    var resultExpression = Expression.Call(typeof(Queryable), command, 
                                           new[] { type, property.PropertyType },
                                           source.AsQueryable().Expression, 
                                           Expression.Quote(orderByExpression));
    return source.AsQueryable().Provider.CreateQuery<TEntity>(resultExpression);
}
查看更多
人间绝色
3楼-- · 2018-12-31 00:03

Thanks to Maarten (Query a collection using PropertyInfo object in LINQ) I got this solution:

myList.OrderByDescending(x => myPropertyInfo.GetValue(x, null)).ToList();

In my case I was working on a "ColumnHeaderMouseClick" (WindowsForm) so just found the specific Column pressed and its correspondent PropertyInfo:

foreach (PropertyInfo column in (new Process()).GetType().GetProperties())
{
    if (column.Name == dgvProcessList.Columns[e.ColumnIndex].Name)
    {}
}

OR

PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();

(be sure to have your column Names matching the object Properties)

Cheers

查看更多
梦醉为红颜
4楼-- · 2018-12-31 00:03

Convert List to IEnumerable or Iquerable, add using System.LINQ.Dynamic namespace, then u can mention the property names in comma seperated string to OrderBy Method which comes by default from System.LINQ.Dynamic.

查看更多
君临天下
5楼-- · 2018-12-31 00:03

Use dynamic linq

just add using System.Linq.Dynamic;

And use it like this to order all your columns:

string sortTypeStr = "ASC"; // or DESC
string SortColumnName = "Age"; // Your column name
query = query.OrderBy($"{SortColumnName} {sortTypeStr}");
查看更多
流年柔荑漫光年
6楼-- · 2018-12-31 00:06

I found the answer. I can use the .AsQueryable<>() extension method to convert my list to IQueryable, then run the dynamic order by against it.

查看更多
明月照影归
7楼-- · 2018-12-31 00:06

Here's something else I found interesting. If your source is a DataTable, you can use dynamic sorting without using Dynamic Linq

DataTable orders = dataSet.Tables["SalesOrderHeader"];
EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         orderby order.Field<DateTime>("OrderDate")
                                         select order;
DataView view = query.AsDataView();
bindingSource1.DataSource = view;

reference: http://msdn.microsoft.com/en-us/library/bb669083.aspx (Using DataSetExtensions)

Here is one more way to do it by converting it to a DataView:

DataTable contacts = dataSet.Tables["Contact"];    
DataView view = contacts.AsDataView();    
view.Sort = "LastName desc, FirstName asc";    
bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
查看更多
登录 后发表回答