Imam ime lastnosti "sort by" v nizu. Za razvrščanje seznama predmetov bom moral uporabiti Lambda/Linq.
Npr:
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();
}
}
Ena stvar, ki bi jo lahko naredili, je, da spremenite Sort
tako, da bo bolje uporabljal lambde.
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);
}
Zdaj lahko pri klicu metode Sort
določite polje za razvrščanje.
Sort(ref employees, e => e.DOB, SortDirection.Descending);
Za pridobitev vrednosti lastnosti lahko uporabite funkcijo Refleksija.
list = list.OrderBy( x => TypeHelper.GetPropertyValue( x, sortBy ) )
.ToList();
Če ima TypeHelper statično metodo, kot je:
public static class TypeHelper
{
public static object GetPropertyValue( object obj, string name )
{
return obj == null ? null : obj.GetType()
.GetProperty( name )
.GetValue( obj, null );
}
}
Morda si boste želeli ogledati tudi Dynamic LINQ iz knjižnice VS2008 Samples. Uporabite lahko razširitev IEnumerable, da seznam pretvorite v IQueryable in nato uporabite razširitev Dynamic link OrderBy.
list = list.AsQueryable().OrderBy( sortBy + " " + sortDirection );
Odgovor za 1. točko:
Morali bi biti sposobni ročno sestaviti drevo izrazov, ki ga lahko posredujete v ukaz OrderBy z uporabo imena kot niza. Lahko pa uporabite refleksijo, kot je predlagano v drugem odgovoru, kar bi bilo morda manj naporno.
Upravi: Tukaj je delujoč primer ročne izgradnje izraznega drevesa. (Razvrščanje po X.Value, če poznamo samo ime "Value" lastnosti). Za to bi lahko (morali) izdelati splošno metodo.
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; }
}
}
Vendar pa je za izgradnjo izraznega drevesa treba poznati posamezne vrste. To je lahko težava v vašem scenariju uporabe, lahko pa tudi ne. Če ne veste, po katerem tipu bi morali razvrščati, bo verjetno lažje uporabiti refleksijo.
Odgovor za 2. točko:
Da, saj bo za primerjavo uporabljen Comparer