Как я могу сделать OrderBy с динамическим параметром строки?
Я хочу сделать это:
var orderBy = "Nome, Cognome desc";
var timb = time.Timbratures.Include("Anagrafica_Dipendente")
.Where(p => p.CodDipendente == 1);
if(orderBy != "")
timb = timb.OrderBy(orderBy);
Доступна ли перегрузка OrderBy
, которая принимает строковый параметр?
Ответы
Ответ 1
Совершенно верно. Вы можете использовать LINQ Dynamic Query Library, найти в блоге Скотта Гатри. Там также доступна обновленная версия в CodePlex.
Он позволяет создавать предложения OrderBy
, предложения Where
и все остальное, передавая строковые параметры. Он отлично работает для создания общего кода для сортировки/фильтрации сетки и т.д.
var result = data
.Where(/* ... */)
.Select(/* ... */)
.OrderBy("Foo asc");
var query = DbContext.Data
.Where(/* ... */)
.Select(/* ... */)
.OrderBy("Foo ascending");
Ответ 2
Если вы используете простые LINQ-to-objects и не хотите зависеть от внешней библиотеки, нетрудно достичь того, чего вы хотите.
Предложение OrderBy()
принимает Func<TSource, TKey>
, который получает ключ сортировки из исходного элемента. Вы можете определить функцию вне предложения OrderBy()
:
Func<Item, Object> orderByFunc = null;
Затем вы можете назначить его различным значениям в зависимости от критериев сортировки:
if (sortOrder == SortOrder.SortByName)
orderByFunc = item => item.Name;
else if (sortOrder == SortOrder.SortByRank)
orderByFunc = item => item.Rank;
Затем вы можете сортировать:
var sortedItems = items.OrderBy(orderByFunc);
В этом примере предполагается, что тип источника Item
имеет свойства Name
и Rank
.
Обратите внимание, что в этом примере TKey
есть Object
, чтобы не ограничивать типы свойств, которые можно сортировать. Если func возвращает тип значения (например, Int32
), он будет помещен в коробку при сортировке и несколько неэффективен. Если вы можете ограничить TKey
определенным типом значения, вы можете обойти эту проблему.
Ответ 3
Другое решение от codeConcussion (fooobar.com/questions/98879/...)
var param = "Address";
var pi = typeof(Student).GetProperty(param);
var orderByAddress = items.OrderBy(x => pi.GetValue(x, null));
Ответ 4
Для этого вам не нужна внешняя библиотека. Следующий код работает для LINQ to SQL/entity.
/// <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
скопирован из fooobar.com/questions/109262/...)
Ответ 5
Самое простое и лучшее решение:
mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s));
Ответ 6
Посмотрите этот блог здесь. Он описывает способ сделать это, определив EntitySorter<T>
.
Он позволяет вам передать IEntitySorter<T>
в свои методы обслуживания и использовать его следующим образом:
public static Person[] GetAllPersons(IEntitySorter<Person> sorter)
{
using (var db = ContextFactory.CreateContext())
{
IOrderedQueryable<Person> sortedList = sorter.Sort(db.Persons);
return sortedList.ToArray();
}
}
И вы можете создать EntitiySorter
следующим образом:
IEntitySorter<Person> sorter = EntitySorter<Person>
.OrderBy(p => p.Name)
.ThenByDescending(p => p.Id);
Или вот так:
var sorter = EntitySorter<Person>
.OrderByDescending("Address.City")
.ThenBy("Id");
Ответ 7
Вам нужно использовать LINQ Dynamic библиотеку запросов, чтобы передавать параметры во время выполнения,
Это позволит использовать выражения linq, такие как
string orderedBy = "Description";
var query = (from p in products
orderby(orderedBy)
select p);
Ответ 8
Я сделал так:
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<Func<TSource, string>>(expressao, parametro); // r => r.AlgumaCoisa
if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase)){
return source.OrderByDescending(lambda);
}
return source.OrderBy(lambda);
}
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
if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase))
{
return source.ThenByDescending(lambda);
}
return source.ThenBy(lambda);
}
}
}
Использование:
example.OrderBy("Nome", "desc").ThenBy("other")
Работайте так:
example.OrderByDescending(r => r.Nome).ThenBy(r => r.other)
Ответ 9
В одном ответе выше:
Самое простое и лучшее решение:
mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s));
Существует синтаксическая ошибка, ,null
должен быть добавлен:
mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s,null));