Фильтровать объекты, затем сортировать по динамическому полю - PullRequest
3 голосов
/ 20 апреля 2011

Я ПЕРВЫЙ пытаюсь отфильтровать набор продуктов, затем заказать их

  (repository.GetAllProducts()
     .Where(x=>x.Naam.Contains("filter")) as ObjectQuery<Product>)
     .FunkyOrder<Product>(sortfield,sortdirection)

Использование метода Extension:

 public  static IEnumerable<T> FunkyOrder<T>(this ObjectQuery<T> input, string fieldname = "Id", string sortdirection = "asc")
        {            
            switch (sortdirection)
            {
                case "dsc":
                case "desc":
                    return input.OrderBy("it." + fieldname + " DESC");
                default:
                    return input.OrderBy("it." + fieldname);

            }
        }

(GetAllProducts () моего репозитория возвращает IEnumerable

Этот метод FunkyOrder должен работать, но это - как ObjectQuery - приведение возвращает NULL

Я могу использовать FunkyOrder только с ObjectQuery, потому что, похоже, это единственное, что поддерживает эти запросы "it.FieldName".

Если я поменяю обозначение - как - на Обычный актерский состав, я получу:

 Unable to cast object of type 'WhereEnumerableIterator`1[MySecretNameSpace.Product]' to type 'System.Data.Objects.ObjectQuery`1[MySecretNameSpace.Product]'.

Есть ли способ заставить это работать, или я буду вынужден либо жить с сортировкой перед фильтрацией, либо написать гигантский переключатель с лямбда-выражениями для моей сортировки?

Ответы [ 3 ]

7 голосов
/ 20 апреля 2011

Это на самом деле оказалось ГИГАНТСКОЙ головной болью, чтобы попытаться ее решить;но, в конце концов, оказалось, что это очень легко сделать с небольшим количеством хакерства и размышлений:

public class Program
{
    public class SomeClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    static void Main(string[] args)
    {
        List<SomeClass> sample = new List<SomeClass>
        {
            new SomeClass { Id = 4, Name = "ABC" },
            new SomeClass { Id = 1, Name = "XYZ" },
            new SomeClass { Id = 2, Name = "JKL" }
        };

        var result = sample.OrderByDynamic("Name", OrderDirection.Ascending).ToList();

        result.ForEach(x => Console.WriteLine("Id: " + x.Id + " | Name: " + x.Name));

        Console.ReadKey();
    }
}

public enum OrderDirection
{
    Ascending,
    Descending
}

public static class LinqExtensions
{
    public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string propertyName, OrderDirection direction = OrderDirection.Ascending)
    {
        if(direction == OrderDirection.Ascending)
            return source.OrderBy(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
        else
            return source.OrderByDescending(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
    }
}

Этот пример сработал для меня в тестовых ситуациях;Я мог бы указать имя свойства и указать направление сортировки, и оно отлично работало.Просто позвоните так:

yourEnumerable.OrderByDynamic("YourPropertyName");
yourEnumerable.OrderByDynamic("YourPropertyName", OrderDirection.Descending);

Наслаждайтесь!

2 голосов
/ 20 апреля 2011

Я бы изменил ваш метод FunkyOrder на IEnumerable и реализовал бы вашу динамическую сортировку, создавая динамическое выражение, например, так:

public static IEnumerable<T> FunkyOrder<T, TResult>(this IEnumerable<T> input, string fieldname = "Id", string sortdirection = "asc")
{
 ParameterExpresssion parameter = Expression.Parameter(typeof(T), "p");
 Expression property = Expression.PropertyOrField(parameter, fieldname);

 var lambda = Expression.Lambda<Func<T, TResult>>(property, parameter)

 if(sortdirection == "asc")
 {
  return input.OrderBy(lambda.Compile());
 }
 else
 {
  return input.OrderByDescending(lambda.Complile());
 }
}

Вам больше не нужно приводить к ObjectQuery

1 голос
/ 20 апреля 2011

Вы можете использовать Dynamic Linq для динамической фильтрации и сортировки. Эта небольшая библиотека (только один исходный файл) содержит методы расширения IQueryable<T>, такие как:

public static IQueryable<T> Where<T>(this IQueryable<T> source,
    string predicate, params object[] values)

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,
    string ordering, params object[] values)

//...and more like GroupBy, Select

Ваш запрос в IEnumerable может быть записан как:

repository.GetAllProducts().AsQueryable()
    .Where(x => x.Naam.Contains("filter"))
    .OrderBy("FieldName desc")

Библиотека реализует весь необходимый код отражения для выполнения этих динамических запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...