ordinamento dinamico in linq

per favore considera questo scenario:

Ho una lista di una class con circa 50 campi. Voglio avere un Combobox che l’utente può selezionare in base a quale elenco di campi sarà ordinato. Ad esempio, se l’utente seleziona la lista “F1” ordina secondo “F1”.

Non voglio ordinare con if-else per ogni campo. Vedo questo argomento:

Ordinamento di una vista a griglia quando si associa una raccolta o un elenco di oggetti

ma non posso usare la sua risposta. Come posso usare Expression Tree per questo scopo?

Grazie

Modifica 1) :

Secondo la cara risposta @Thom Smith ho scritto questo codice:

  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(); } 

ma non è stato ordinato. se ho scritto quel codice in questo modo:

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

essendo sorta. dov’è il problema?

OrderBy non esegue un ordinamento sul posto. Restituisce una sequenza che, una volta valutata, verrà ordinata. Questo di solito viene fatto pigramente, cioè: finché non viene enumerato, non fa nulla . Il tuo codice attuale semplicemente scarta questo importantissimo valore di ritorno. La correzione è semplice: prendi il valore di ritorno:

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

Nota: analogamente, l’applicazione “Dove” non filtra i dati esistenti: restituisce una sequenza che quando viene enumerata viene filtrata. Quindi se stavi filtrando avresti il ​​simile:

 query = query.Where(...); 

Ecco il metodo che uso per questo:

 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 è solo una struttura con un attributo e una direzione.

EDIT: spiegazione aggiuntiva.

Questo metodo proviene dalla mia class DynamicOrderList , che è un elenco di oggetti OrderParameter . Se tutto ciò di cui hai bisogno è l’ordinamento per un campo, puoi semplificarlo un po ‘:

 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 } } 

Quindi usarlo come:

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

MODIFICA 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 } } 

E:

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

Dai un’occhiata a questo link Ordinamento di più campi per nome dei campi usando Linq

Spero che possa aiutare a realizzare ciò di cui hai bisogno.

Ecco la mia versione più recente, utilizzando Enumerable + Reflection anziché query:

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

Spero che sarà utile Ha funzionato per Me per filtrare la lista C # in modo dinamico

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