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);
Y a-t-il une surcharge OrderBy
disponible qui accepte un paramètre de chaîne?
Absolument. Vous pouvez utiliser la bibliothèque de requêtes dynamiques LINQ, trouvée 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
, Where
clauses, et à peu près tout le reste en passant des paramètres de chaîne. Cela fonctionne très bien pour créer du code générique pour les grilles de tri/filtrage, etc.
var result = data
.Where(/* ... */)
.Select(/* ... */)
.OrderBy("Foo asc");
var query = DbContext.Data
.Where(/* ... */)
.Select(/* ... */)
.OrderBy("Foo ascending");
Si vous utilisez des LINQ-to-objects simples 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<TSource, TKey>
Qui obtient une clé de tri à partir d'un élément source. Vous pouvez définir la fonction en dehors de la clause OrderBy()
:
Func<Item, Object> orderByFunc = null;
Vous pouvez ensuite l'affecter à différentes valeurs en fonction des critères de tri:
if (sortOrder == SortOrder.SortByName)
orderByFunc = item => item.Name;
else if (sortOrder == SortOrder.SortByRank)
orderByFunc = item => item.Rank;
Ensuite, vous pouvez trier:
var sortedItems = items.OrderBy(orderByFunc);
Cet exemple suppose que le type de source est Item
qui possède les propriétés Name
et Rank
.
Notez que dans cet exemple TKey
est Object
pour ne pas contraindre les types de propriétés qui peuvent être triés. Si la fonction renvoie un type de valeur (comme Int32
), Elle sera encadrée lors du tri et cela 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.
/// <summary>
/// Sorts the elements of a sequence according to a key and the sort order.
/// </summary>
/// <typeparam name="TSource">The type of the elements of <paramref name="query" />.</typeparam>
/// <param name="query">A sequence of values to order.</param>
/// <param name="key">Name of the property of <see cref="TSource"/> by which to sort the elements.</param>
/// <param name="ascending">True for ascending order, false for descending order.</param>
/// <returns>An <see cref="T:System.Linq.IOrderedQueryable`1" /> whose elements are sorted according to a key and sort order.</returns>
public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> query, string key, bool ascending = true)
{
if (string.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, string 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é 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 un moyen de le faire, en définissant un EntitySorter<T>
.
Il vous permet de passer un IEntitySorter<T>
dans vos méthodes de service et utilisez-le comme ceci:
public static Person[] GetAllPersons(IEntitySorter<Person> sorter)
{
using (var db = ContextFactory.CreateContext())
{
IOrderedQueryable<Person> sortedList = sorter.Sort(db.Persons);
return sortedList.ToArray();
}
}
Et vous pouvez créer un EntitiySorter
comme ceci:
IEntitySorter<Person> sorter = EntitySorter<Person>
.OrderBy(p => p.Name)
.ThenByDescending(p => p.Id);
Ou comme ça:
var sorter = EntitySorter<Person>
.OrderByDescending("Address.City")
.ThenBy("Id");
Je l'ai fait:
using System.Linq.Expressions;
namespace System.Linq
{
public static class LinqExtensions
{
public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string field, string 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
var tipo = typeof(TSource).GetProperty(field).PropertyType;
var nome = "OrderBy";
if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase))
{
nome = "OrderByDescending";
}
var metodo = typeof(Queryable).GetMethods().First(m => m.Name == nome && m.GetParameters().Length == 2);
var metodoGenerico = metodo.MakeGenericMethod(new[] { typeof(TSource), tipo });
return metodoGenerico.Invoke(source, new object[] { source, lambda }) as IOrderedQueryable<TSource>;
}
public static IOrderedQueryable<TSource> ThenBy<TSource>(this IOrderedQueryable<TSource> source, string field, string dir = "asc")
{
var parametro = Expression.Parameter(typeof(TSource), "r");
var expressao = Expression.Property(parametro, field);
var lambda = Expression.Lambda<Func<TSource, string>>(expressao, parametro); // r => r.AlgumaCoisa
var tipo = typeof(TSource).GetProperty(field).PropertyType;
var nome = "ThenBy";
if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase))
{
nome = "ThenByDescending";
}
var metodo = typeof(Queryable).GetMethods().First(m => m.Name == nome && m.GetParameters().Length == 2);
var metodoGenerico = metodo.MakeGenericMethod(new[] { typeof(TSource), tipo });
return metodoGenerico.Invoke(source, new object[] { source, lambda }) as IOrderedQueryable<TSource>;
}
}
}
Utilisation :
example.OrderBy("Nome", "desc").ThenBy("other")
Fonctionne comme:
example.OrderByDescending(r => r.Nome).ThenBy(r => r.other)
Vous devez utiliser la bibliothèque de requêtes LINQ Dynamic afin de passer les paramètres au moment de l'exécution,
Cela permettra aux instructions linq comme
string orderedBy = "Description";
var query = (from p in products
orderby(orderedBy)
select p);