Mám názov vlastnosti "sort by" v reťazci. Na zoradenie zoznamu objektov budem potrebovať použiť Lambda/Linq.
Napr:
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();
}
}
Jednou z vecí, ktorú by ste mohli urobiť, je zmeniť Sort
tak, aby lepšie využíval lambdy.
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);
}
Teraz môžete pri volaní metódy Sort
určiť pole, ktoré sa má triediť.
Sort(ref employees, e => e.DOB, SortDirection.Descending);
Na získanie hodnoty vlastnosti môžete použiť funkciu Reflection.
list = list.OrderBy( x => TypeHelper.GetPropertyValue( x, sortBy ) )
.ToList();
Kde TypeHelper má statickú metódu ako napr:
public static class TypeHelper
{
public static object GetPropertyValue( object obj, string name )
{
return obj == null ? null : obj.GetType()
.GetProperty( name )
.GetValue( obj, null );
}
}
Možno sa budete chcieť pozrieť aj na Dynamic LINQ z knižnice VS2008 Samples. Mohli by ste použiť rozšírenie IEnumerable na obsadenie zoznamu ako IQueryable a potom použiť rozšírenie Dynamic link OrderBy.
list = list.AsQueryable().OrderBy( sortBy + " " + sortDirection );
Odpoveď pre 1.:
Mali by ste byť schopní ručne vytvoriť strom výrazov, ktorý sa dá odovzdať do OrderBy pomocou názvu ako reťazca. alebo môžete použiť reflexiu, ako sa navrhuje v inej odpovedi, čo by mohlo byť menej pracné.
Edit: Tu je funkčný príklad ručného zostavenia stromu výrazov. (Triedenie podľa X.Value, keď poznáme len názov "Value" vlastnosti). Mohli (mali by ste) vytvoriť všeobecnú metódu na jej vykonávanie.
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; }
}
}
Vytvorenie stromu výrazov si však vyžaduje, aby ste poznali jednotlivé typy. To môže, ale nemusí byť problém vo vašom scenári použitia. Ak neviete, na základe akého typu by ste mali triediť, bude pravdepodobne jednoduchšie použiť reflexiu.
Odpoveď pre bod 2:
Áno, pretože na porovnávanie sa použije Comparer