Ho il nome della proprietà "sort by" in una stringa. Ho bisogno di usare Lambda/Linq per ordinare l'elenco degli oggetti.
Es:
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();
}
}
Una cosa che potreste fare è cambiare Sort
in modo che faccia un uso migliore dei lambda.
public enum SortDirection { Ascending, Descending }
public void Sort<TKey>(ref List<Employee> list,
Func<Employee, TKey> sorter, SortDirection direction)
{
if (direction == SortDirection.Ascending)
list = list.OrderBy(sorter);
else
list = list.OrderByDescending(sorter);
}
Ora si può specificare il campo da ordinare quando si chiama il metodo Sort
.
Sort(ref employees, e => e.DOB, SortDirection.Descending);
Potreste usare Reflection per ottenere il valore della proprietà.
list = list.OrderBy( x => TypeHelper.GetPropertyValue( x, sortBy ) )
.ToList();
Dove TypeHelper ha un metodo statico come:
public static class TypeHelper
{
public static object GetPropertyValue( object obj, string name )
{
return obj == null ? null : obj.GetType()
.GetProperty( name )
.GetValue( obj, null );
}
}
Potresti anche voler guardare Dynamic LINQ dalla libreria VS2008 Samples. Potresti usare l'estensione IEnumerable per lanciare la lista come un IQueryable e poi usare l'estensione Dynamic link OrderBy.
list = list.AsQueryable().OrderBy( sortBy + " " + sortDirection );
Risposta per 1.:
Dovresti essere in grado di costruire manualmente un albero di espressione che può essere passato in OrderBy usando il nome come stringa. Or potresti usare la riflessione come suggerito in un'altra risposta, che potrebbe essere meno lavoro.
Edit: Ecco un esempio funzionante di costruzione manuale di un albero di espressione. (Ordinamento su X.Value, quando si conosce solo il nome "Value" della proprietà). Si potrebbe (dovrebbe) costruire un metodo generico per farlo.
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<Func<X, int>>(expression, pe).Compile();
foreach (var n in randX.OrderBy(exp))
Console.WriteLine(n.Value);
}
public class X
{
public int Value { get; set; }
}
}
Costruire un albero di espressioni richiede di conoscere i tipi partecipanti, tuttavia. Questo potrebbe essere o meno un problema nel tuo scenario d'uso. Se non sapete su quale tipo dovreste fare l'ordinamento, sarà probabilmente più facile usare la riflessione.
Risposta per 2.:
Sì, poiché Comparer