Yar*_*rik 7 c# linq lambda expression
我正在尝试构建一个用于排序的表达式,并且我编写了使用一个属性对列表进行排序的代码.
但我需要首先将其分类为一个属性,其次是另一个属性,依此类推.
我的意思是我想构建一个表达式来实现类似的东西:students.OrderBy(fistExpression.Compile()).ThenBy(secondImpression.Complie()).ThenBy(thirdExpression.Compile())
.
那么如何动态地放置那些ThenBy
方法呢?
这是我的代码:
Type studentType = typeof(Student);
ParameterExpression studentParam = Expression.Parameter(studentType, "x");
MemberInfo ageProperty = studentType.GetProperty("Age");
MemberExpression valueInNameProperty =
Expression.MakeMemberAccess(studentParam, ageProperty);
Expression<Func<Student, int>> orderByExpression =
Expression<Func<Student, int>>.Lambda<Func<Student, int>>(valueInNameProperty, studentParam);
var sortedStudents = students.OrderBy(orderByExpression.Compile());
Run Code Online (Sandbox Code Playgroud)
我的解决方案:
public static Func<Student, object> BuildPredicate(string propertyName)
{
Type studentType = typeof(Student);
ParameterExpression studentParam = Expression.Parameter(studentType, "x");
MemberInfo ageProperty = studentType.GetProperty(propertyName);
MemberExpression valueInNameProperty = Expression.MakeMemberAccess(studentParam, ageProperty);
UnaryExpression expression = Expression.Convert(valueInNameProperty, typeof (object));
Expression<Func<Student, object>> orderByExpression = Expression.Lambda<Func<Student, object>>(expression, studentParam);
return orderByExpression.Compile();
}
Run Code Online (Sandbox Code Playgroud)
在您的表达式制作代码中添加了转换为object
.
这就是创建链的方法ThenBy
:
var sortedStudents = students.OrderBy(BuildPredicate("Age"));
foreach (var property in typeof(Student).GetProperties().Where(x => !String.Equals(x.Name, "Age")))
{
sortedStudents = sortedStudents.ThenBy(BuildPredicate(property.Name));
}
var result = sortedStudents.ToList();
Run Code Online (Sandbox Code Playgroud)
最后,Student
示例类:
public class Student
{
public int Age { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
更新:
另一种方法是使用属性来标记您的属性,以便在和Student
中使用它们。喜欢:OrderBy
ThenBy
public class Student
{
[UseInOrderBy]
public int Age { get; set; }
[UseInOrderBy(Order = 1)]
public string Name { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
internal class UseInOrderByAttribute : Attribute
{
public int Order { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这就是您如何使用以下方法构建排序链UseInOrderByAttribute
:
Type studentType = typeof (Student);
var properties = studentType.GetProperties()
.Select(x => new { Property = x, OrderAttribute = x.GetCustomAttribute<UseInOrderByAttribute>() })
.Where(x => x.OrderAttribute != null)
.OrderBy(x => x.OrderAttribute.Order);
var orderByProperty = properties.FirstOrDefault(x => x.OrderAttribute.Order == 0);
if (orderByProperty == null)
throw new Exception("");
var sortedStudents = students.OrderBy(BuildPredicate(orderByProperty.Property.Name));
foreach (var property in properties.Where(x => x.Property.Name != orderByProperty.Property.Name))
{
sortedStudents = sortedStudents.ThenBy(BuildPredicate(property.Property.Name));
}
var result = sortedStudents.ToList();
Run Code Online (Sandbox Code Playgroud)
修复:BuildPredicate
可以不用dynamic
. BuildPredicate
示例代码已更改。
归档时间: |
|
查看次数: |
1914 次 |
最近记录: |