Pergunta

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

alguém pode me ajudar?

Foi útil?

Solução

Se você quiser este olhar funcionalidade em um artigo de ScottGu na Biblioteca Linq dinâmico . Eu acredito que ele vai fazer o que quiser.

Enquanto Lambda são do tipo seguro há momentos em que você pode querer gerar em tempo real a consulta ao invés de ter todas as combinações possíveis que um usuário pode classificar por exemplo.

Editar

Eu fixo o seu método. Basicamente, você precisa criar uma expressão para cada acesso de membro.

 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;
        }
    }

Outras dicas

Você pode querer pensar sobre um outro método que leva um comparador objeto personalizado para fazer a comparação. Você poderia, então, escrever um comparador personalizado para a pessoa que os compara com base em seus endereços de email.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top