Метод расширения для сортировки списка внутри родительского объекта

StackOverflow https://stackoverflow.com/questions/802789

  •  03-07-2019
  •  | 
  •  

Вопрос

public class Person
{
    public string name { get; set; }
    public Email email { get; set; }

}

public class Email
{
    public string desc { get; set; }
}

public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression, bool desc)
{            
    var param = Expression.Parameter(typeof(T), string.Empty);
    try
    {
        var property   = Expression.Property(param, sortExpression);
        var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);

        if (desc)
        {
            return source.AsQueryable<T>().OrderByDescending<T, object>(sortLambda);
        }

        return source.AsQueryable<T>().OrderBy<T, object>(sortLambda);
    }
    catch (ArgumentException)
    {
        return source;
    }
}

        List<Person> vet = new List<Person>();

        Person p = new Person { name = "aaa", email = new Email { desc = "bbb@aaa.com" } };
        Person pp = new Person { name = "bbb", email = new Email { desc = "aaa@aaa.com" } };
        vet.Add(p);
        vet.Add(pp);

        vet.Sort("name",true); //works
        vet.Sort("email.desc",true) // doesnt work

кто-нибудь может мне помочь?

Это было полезно?

Решение

Если вам нужна эта функциональность, прочтите статью ScottGu на Динамическая библиотека Linq.Я верю, что он сделает то, что вы хотите.

Несмотря на то, что Lambda являются типобезопасными, бывают случаи, когда вам может потребоваться сгенерировать запрос на лету, а не использовать, например, все возможные комбинации, которые пользователь может отсортировать.

Редактировать

Я исправил ваш метод.По сути, вам нужно создать выражение для доступа к каждому члену.

 public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression, bool desc)
    {
        var param = Expression.Parameter(typeof(T), string.Empty);
        try
        {
            var fields = sortExpression.Split('.');
            Expression property = null;
            Expression parentParam = param;
            foreach (var field in fields)
            {
                property = Expression.Property(parentParam, field);
                parentParam = property;

            }

            var sortLambda = 
                Expression.Lambda<Func<T, object>>(
                  Expression.Convert(property, typeof(object)), param);

            if (desc)
            {
                return source.AsQueryable<T>().
                     OrderByDescending<T, object>(sortLambda);
            }

            return source.AsQueryable<T>().
                 OrderBy<T, object>(sortLambda);
        }
        catch (ArgumentException)
        {
            throw;
        }
    }

Другие советы

Возможно, вам захочется подумать о другом методе, который использует для сравнения собственный объект Comparer.Затем вы можете написать собственный инструмент сравнения для людей, который сравнивает их на основе их адресов электронной почты.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top