J'ai une méthode qui reçoit le paramètre "bool sortAscending". Maintenant, je veux utiliser LINQ pour créer une liste triée en fonction de ce paramètre. J'ai eu alors ceci:
var ascendingQuery = from data in dataList
orderby data.Property ascending
select data;
var descendingQuery = from data in dataList
orderby data.Property descending
select data;
Comme vous pouvez le constater, les deux requêtes ne diffèrent que par "ascendant" resp. "descendant". J'aimerais fusionner les deux requêtes, mais je ne sais pas comment. Est-ce que quelqu'un a la réponse?
Vous pouvez facilement créer votre propre méthode d’extension sur IEnumerable ou IQueryable:
public static IOrderedEnumerable<TSource> OrderByWithDirection<TSource,TKey>
(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
bool descending)
{
return descending ? source.OrderByDescending(keySelector)
: source.OrderBy(keySelector);
}
public static IOrderedQueryable<TSource> OrderByWithDirection<TSource,TKey>
(this IQueryable<TSource> source,
Expression<Func<TSource, TKey>> keySelector,
bool descending)
{
return descending ? source.OrderByDescending(keySelector)
: source.OrderBy(keySelector);
}
Oui, vous perdez la possibilité d'utiliser une expression de requête ici - mais franchement, je ne pense pas que vous tiriez réellement profit d'une expression de requête de toute façon dans ce cas. Les expressions de requête conviennent parfaitement aux choses complexes, mais si vous ne faites qu'une seule opération, il est plus simple de simplement mettre cette opération:
var query = dataList.OrderByWithDirection(x => x.Property, direction);
En termes de mise en œuvre, cela change la méthode - de OrderBy/ThenBy à OrderByDescending/ThenByDescending. Cependant, vous pouvez appliquer le tri séparément à la requête principale ...
var qry = from .... // or just dataList.AsEnumerable()/AsQueryable()
if(sortAscending) {
qry = qry.OrderBy(x=>x.Property);
} else {
qry = qry.OrderByDescending(x=>x.Property);
}
Toute utilisation? Vous pouvez créer l'intégralité de la "commande" de manière dynamique, mais elle est plus complexe ...
Une autre astuce (principalement appropriée à LINQ-to-Objects) consiste à utiliser un multiplicateur, de -1/1. Cela n’est vraiment utile que pour les données numériques, mais c’est un moyen effronté d’atteindre le même résultat.
Qu'en est-il de commander desc par la propriété désirée,
blah = blah.OrderByDescending(x => x.Property);
Et puis faire quelque chose comme
if (!descending)
{
blah = blah.Reverse()
}
else
{
// Already sorted desc ;)
}
Est-ce que c'est Reverse () trop lent?
En plus de la belle solution donnée par @Jon Skeet, j'avais également besoin de ThenBy et ThenByDescending, je l'ajoute donc en fonction de sa solution:
public static IOrderedEnumerable<TSource> ThenByWithDirection<TSource, TKey>(
this IOrderedEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
bool descending)
{
return descending ?
source.ThenByDescending(keySelector) :
source.ThenBy(keySelector);
}