Ordenação de uma lista usando Lambda/Linq para objetos

Eu tenho o nome do " ordenar por propriedade" em um fio. Vou precisar usar Lambda/Linq para ordenar a lista de objetos.

Ex:

public class Employee
{
  public string FirstName {set; get;}
  public string LastName {set; get;}
  public DateTime DOB {set; get;}
}

public void Sort(ref List<Employee> list, string sortBy, string sortDirection)
{
  //Example data:
  //sortBy = "FirstName"
  //sortDirection = "ASC" or "DESC"

  if (sortBy == "FirstName")
  {
    list = list.OrderBy(x => x.FirstName).toList();    
  }

}
  1. Em vez de usar um monte de ifs para verificar o nome do campo (sortBy), existe uma maneira mais limpa de fazer a ordenação
  2. Está mais ou menos ciente do tipo de dados?

Uma coisa que você pode fazer é mudar o 'Classificar' para que ele faça melhor uso das lambdas.

public enum SortDirection { Ascending, Descending }
public void Sort(ref List list,
                       Func sorter, SortDirection direction)
{
  if (direction == SortDirection.Ascending)
    list = list.OrderBy(sorter);
  else
    list = list.OrderByDescending(sorter);
}

Agora você pode especificar o campo a ser ordenado ao chamar o método `Sortar'.

Sort(ref employees, e => e.DOB, SortDirection.Descending);
Comentários (7)

Você poderia usar o Reflection para obter o valor do imóvel.

list = list.OrderBy( x => TypeHelper.GetPropertyValue( x, sortBy ) )
           .ToList();

Onde o TypeHelper tem um método estático como:

public static class TypeHelper
{
    public static object GetPropertyValue( object obj, string name )
    {
        return obj == null ? null : obj.GetType()
                                       .GetProperty( name )
                                       .GetValue( obj, null );
    }
}

Você também pode querer olhar o Dynamic LINQ da VS2008 Samples library. Você pode usar a extensão IEnumerable para lançar a Lista como um IQueryable e então usar a extensão Dynamic link OrderBy.

 list = list.AsQueryable().OrderBy( sortBy + " " + sortDirection );
Comentários (7)

Resposta para 1.:

Você deve ser capaz de construir manualmente uma árvore de expressões que pode ser passada para OrderBy usando o nome como uma string. Or você pode usar a reflexão como sugerido em outra resposta, o que pode ser menos trabalhoso.

Editar: Aqui está um exemplo de como construir uma árvore de expressão manualmente. (Ordenação no X.Value, quando se conhece apenas o nome "Value" do imóvel). Você poderia (deveria) construir um método genérico para fazer isso.

using System;
using System.Linq;
using System.Linq.Expressions;

class Program
{
    private static readonly Random rand = new Random();
    static void Main(string[] args)
    {
        var randX = from n in Enumerable.Range(0, 100)
                    select new X { Value = rand.Next(1000) };

        ParameterExpression pe = Expression.Parameter(typeof(X), "value");
        var expression = Expression.Property(pe, "Value");
        var exp = Expression.Lambda(expression, pe).Compile();

        foreach (var n in randX.OrderBy(exp))
            Console.WriteLine(n.Value);
    }

    public class X
    {
        public int Value { get; set; }
    }
}

A construção de uma árvore de expressão requer, no entanto, que você conheça os tipos de partículas. Isso pode ou não ser um problema no seu cenário de utilização. Se você não'não sabe em que tipo você deve estar classificando, provavelmente será mais fácil usar a reflexão.

Resposta para 2.:

Sim, desde Comparador&lificador;lt;T&lificador;gt;.O padrão será usado para a comparação, se você não definir explicitamente o comparador.

Comentários (1)