Dot*_*ude 264 c# linq lambda linq-to-objects
我在字符串中有"按属性排序"的名称.我将需要使用Lambda/Linq对对象列表进行排序.
例如:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
gls*_*123 352
这可以做到
list.Sort( (emp1,emp2)=>emp1.FirstName.CompareTo(emp2.FirstName) );
Run Code Online (Sandbox Code Playgroud)
.NET框架将lambda转换(emp1,emp2)=>int为Comparer<Employee>.
这具有强类型的优点.
Sam*_*uel 74
你可以做的一件事就是改变,Sort以便更好地利用lambdas.
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);
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以在调用Sort方法时指定要排序的字段.
Sort(ref employees, e => e.DOB, SortDirection.Descending);
Run Code Online (Sandbox Code Playgroud)
tva*_*son 55
您可以使用Reflection来获取属性的值.
list = list.OrderBy( x => TypeHelper.GetPropertyValue( x, sortBy ) )
.ToList();
Run Code Online (Sandbox Code Playgroud)
TypeHelper有一个静态方法,如:
public static class TypeHelper
{
public static object GetPropertyValue( object obj, string name )
{
return obj == null ? null : obj.GetType()
.GetProperty( name )
.GetValue( obj, null );
}
}
Run Code Online (Sandbox Code Playgroud)
您可能还想查看VS2008 Samples库中的 Dynamic LINQ .您可以使用IEnumerable扩展将List强制转换为IQueryable,然后使用动态链接OrderBy扩展.
list = list.AsQueryable().OrderBy( sortBy + " " + sortDirection );
Run Code Online (Sandbox Code Playgroud)
小智 20
这就是我解决问题的方法:
List<User> list = GetAllUsers(); //Private Method
if (!sortAscending)
{
list = list
.OrderBy(r => r.GetType().GetProperty(sortBy).GetValue(r,null))
.ToList();
}
else
{
list = list
.OrderByDescending(r => r.GetType().GetProperty(sortBy).GetValue(r,null))
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
Ras*_*ack 15
可以在此处阅读通过表达式构建订单
链接中的页面无耻地被盗:
// First we define the parameter that we are going to use
// in our OrderBy clause. This is the same as "(person =>"
// in the example above.
var param = Expression.Parameter(typeof(Person), "person");
// Now we'll make our lambda function that returns the
// "DateOfBirth" property by it's name.
var mySortExpression = Expression.Lambda<Func<Person, object>>(Expression.Property(param, "DateOfBirth"), param);
// Now I can sort my people list.
Person[] sortedPeople = people.OrderBy(mySortExpression).ToArray();
Run Code Online (Sandbox Code Playgroud)
您可以使用反射来访问该属性.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
笔记
如果类型实现了,则使用IComparable接口.您可以通过实现自定义IComparer来避免ifs:
class EmpComp : IComparer<Employee>
{
string fieldName;
public EmpComp(string fieldName)
{
this.fieldName = fieldName;
}
public int Compare(Employee x, Employee y)
{
// compare x.fieldName and y.fieldName
}
}
Run Code Online (Sandbox Code Playgroud)
然后
list.Sort(new EmpComp(sortBy));
Run Code Online (Sandbox Code Playgroud)
答案1:
您应该能够使用名称作为字符串手动构建可以传递到OrderBy的表达式树.或者您可以使用另一个答案中建议的反射,这可能会减少工作量.
编辑:以下是手动构建表达式树的工作示例.(在X.Value上排序,只知道属性的名称"Value").你可以(应该)构建一个通用的方法来做到这一点.
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; }
}
}
Run Code Online (Sandbox Code Playgroud)
但是,构建表达式树需要您了解参与类型.在您的使用场景中,这可能是也可能不是问题.如果您不知道应该对哪种类型进行排序,那么使用反射将更容易.
回答2:
是的,因为如果没有明确定义比较器,将使用Comparer <T> .Default进行比较.
不幸的是,Rashack 提供的解决方案不适用于值类型(int、枚举等)。
为了让它适用于任何类型的属性,这是我找到的解决方案:
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;
}
Run Code Online (Sandbox Code Playgroud)