我在字符串中有“按属性排序”的名称。我需要使用Lambda/Linq对对象列表进行排序。
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();
}
}
与其使用一堆if来检查字段名(sortBy),还有一种更干净的排序方式吗
排序是否知道数据类型?
您可以使用反射来访问该属性。
public List<Employee> Sort(List<Employee> list, String sortBy, String sortDirection)
{
PropertyInfo property = list.GetType().GetGenericArguments()[0].
GetType().GetProperty(sortBy);
if (sortDirection == "ASC")
{
return list.OrderBy(e => property.GetValue(e, null));
}
if (sortDirection == "DESC")
{
return list.OrderByDescending(e => property.GetValue(e, null));
}
else
{
throw new ArgumentOutOfRangeException();
}
}
笔记
你为什么要传阅这份名单?
您应该使用枚举作为排序方向。
如果传递一个lambda表达式,可以得到一个更简洁的解决方案
指定要排序的属性,而不是以字符串形式指定属性名。
在我的例子中,list == null将导致NullReferenceException,您应该捕获这种情况。
您可以使用Reflection来获取属性的值。
list = list.OrderBy( x => TypeHelper.GetPropertyValue( x, sortBy ) )
.ToList();
TypeHelper有一个静态方法,比如:
public static class TypeHelper
{
public static object GetPropertyValue( object obj, string name )
{
return obj == null ? null : obj.GetType()
.GetProperty( name )
.GetValue( obj, null );
}
}
你可能还想看看VS2008 Samples库中的Dynamic LINQ。您可以使用IEnumerable扩展将List转换为IQueryable,然后使用Dynamic link OrderBy扩展。
list = list.AsQueryable().OrderBy( sortBy + " " + sortDirection );
不幸的是,Rashack提供的解决方案不适用于值类型(int、enum等)。
对于任何类型的属性,这是我发现的解决方案:
public static Expression<Func<T, object>> GetLambdaExpressionFor<T>(this string sortColumn)
{
var type = typeof(T);
var parameterExpression = Expression.Parameter(type, "x");
var body = Expression.PropertyOrField(parameterExpression, sortColumn);
var convertedBody = Expression.MakeUnary(ExpressionType.Convert, body, typeof(object));
var expression = Expression.Lambda<Func<T, object>>(convertedBody, new[] { parameterExpression });
return expression;
}