Comment puis-je faire un OrderBy avec un paramètre de chaîne dynamic?

Je veux faire ça:

var orderBy = "Nome, Cognome desc"; var timb = time.Timbratures.Include("Anagrafica_Dipendente") .Where(p => p.CodDipendente == 1); if(orderBy != "") timb = timb.OrderBy(orderBy); 

Existe-t-il une surcharge OrderBy disponible qui accepte un paramètre de chaîne?

Absolument. Vous pouvez utiliser la bibliothèque de requête dynamic LINQ, disponible sur le blog de Scott Guthrie . Il existe également une version mise à jour disponible sur CodePlex .

Il vous permet de créer des clauses OrderBy clauses Where et à peu près tout le rest en transmettant des parameters de chaîne. Cela fonctionne très bien pour créer le code générique pour les grids de sorting / filtrage, etc.

 var result = data .Where(/* ... */) .Select(/* ... */) .OrderBy("Foo asc"); var query = DbContext.Data .Where(/* ... */) .Select(/* ... */) .OrderBy("Foo ascending"); 

Si vous utilisez des objects LINQ-to-plain et que vous ne voulez pas dépendre d’une bibliothèque externe, il n’est pas difficile d’obtenir ce que vous voulez.

La clause OrderBy() accepte un Func qui obtient une clé de sorting d’un élément source. Vous pouvez définir la fonction en dehors de la clause OrderBy() :

 Func orderByFunc = null; 

Vous pouvez ensuite l’affecter à différentes valeurs en fonction des critères de sorting:

 if (sortOrder == SortOrder.SortByName) orderByFunc = item => item.Name; else if (sortOrder == SortOrder.SortByRank) orderByFunc = item => item.Rank; 

Ensuite, vous pouvez sortinger:

 var sortedItems = items.OrderBy(orderByFunc); 

Cet exemple suppose que le type de source est Item ayant des propriétés Name et Rank .

Notez que dans cet exemple, TKey est Object pour ne pas contraindre les types de propriété pouvant être sortingés. Si le func renvoie un type de valeur (comme Int32 ), il sera mis en boîte lors du sorting, ce qui est quelque peu inefficace. Si vous pouvez contraindre TKey à un type de valeur spécifique, vous pouvez contourner ce problème.

Une autre solution de codeConcussion ( https://stackoverflow.com/a/7265394/2793768 )

 var param = "Address"; var pi = typeof(Student).GetProperty(param); var orderByAddress = items.OrderBy(x => pi.GetValue(x, null)); 

Vous n’avez pas besoin d’une bibliothèque externe pour cela. Le code ci-dessous fonctionne pour LINQ to SQL / Entités.

  ///  /// Sorts the elements of a sequence according to a key and the sort order. ///  /// The type of the elements of . /// A sequence of values to order. /// Name of the property of  by which to sort the elements. /// True for ascending order, false for descending order. /// An  whose elements are sorted according to a key and sort order. public static IQueryable OrderBy(this IQueryable query, ssortingng key, bool ascending = true) { if (ssortingng.IsNullOrWhiteSpace(key)) { return query; } var lambda = (dynamic)CreateExpression(typeof(TSource), key); return ascending ? Queryable.OrderBy(query, lambda) : Queryable.OrderByDescending(query, lambda); } private static LambdaExpression CreateExpression(Type type, ssortingng propertyName) { var param = Expression.Parameter(type, "x"); Expression body = param; foreach (var member in propertyName.Split('.')) { body = Expression.PropertyOrField(body, member); } return Expression.Lambda(body, param); } 

( CreateExpression copié à partir de https://stackoverflow.com/a/16208620/111438 )

La solution la plus simple et la meilleure:

 mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s)); 

Regardez ce blog ici . Il décrit une manière de procéder en définissant un EntitySorter .

Il vous permet de passer un IEntitySorter dans vos méthodes de service et de l’utiliser comme ceci:

 public static Person[] GetAllPersons(IEntitySorter sorter) { using (var db = ContextFactory.CreateContext()) { IOrderedQueryable sortedList = sorter.Sort(db.Persons); return sortedList.ToArray(); } } 

Et vous pouvez créer un EntitiySorter comme ceci:

 IEntitySorter sorter = EntitySorter .OrderBy(p => p.Name) .ThenByDescending(p => p.Id); 

Ou comme ça:

 var sorter = EntitySorter .OrderByDescending("Address.City") .ThenBy("Id"); 

Vous devez utiliser la bibliothèque de requêtes dynamic LINQ pour transmettre les parameters à l’exécution,

Cela permettra des instructions linq comme

 ssortingng orderedBy = "Description"; var query = (from p in products orderby(orderedBy) select p); 

Je l’ai fait:

 using System.Linq.Expressions; namespace System.Linq { public static class LinqExtensions { public static IOrderedQueryable OrderBy(this IQueryable source, ssortingng field, ssortingng dir = "asc") { // parametro => expressão var parametro = Expression.Parameter(typeof(TSource), "r"); var expressao = Expression.Property(parametro, field); var lambda = Expression.Lambda>(expressao, parametro); // r => r.AlgumaCoisa if (ssortingng.Equals(dir, "desc", SsortingngComparison.InvariantCultureIgnoreCase)){ return source.OrderByDescending(lambda); } return source.OrderBy(lambda); } public static IOrderedQueryable ThenBy(this IOrderedQueryable source, ssortingng field, ssortingng dir = "asc") { var parametro = Expression.Parameter(typeof(TSource), "r"); var expressao = Expression.Property(parametro, field); var lambda = Expression.Lambda>(expressao, parametro); // r => r.AlgumaCoisa if (ssortingng.Equals(dir, "desc", SsortingngComparison.InvariantCultureIgnoreCase)) { return source.ThenByDescending(lambda); } return source.ThenBy(lambda); } } } 

Utilisation :

 example.OrderBy("Nome", "desc").ThenBy("other") 

Travailler comme:

 example.OrderByDescending(r => r.Nome).ThenBy(r => r.other) 

Dans une réponse ci-dessus:

La solution la plus simple et la meilleure:

 mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s)); 

Il y a une erreur de syntaxe ,null il faut append ,null :

 mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s,null));