加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用多个排序构建表达式

发布时间:2020-12-15 07:54:59 所属栏目:百科 来源:网络整理
导读:我正在尝试构建一个用于排序的表达式,并且我编写了使用一个属性对列表进行排序的代码. 但我需要首先将其分类为一个属性,其次是另一个属性,依此类推. 我的意思是我想构建一个表达式来实现类似的东西:students.OrderBy(fistExpression.Compile()).ThenBy(seco
我正在尝试构建一个用于排序的表达式,并且我编写了使用一个属性对列表进行排序的代码.

但我需要首先将其分类为一个属性,其次是另一个属性,依此类推.

我的意思是我想构建一个表达式来实现类似的东西: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());

解决方法

我的解决方案
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();
}

在您的表达式中,将代码添加到对象中.

这就是你如何创建一个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();

最后,学生样本班:

public class Student
{
    public int Age { get; set; }
    public string Name { get; set; } 
}

更新:

另一种方法是使用属性来标记学生的属性,以便在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; }
}

这就是使用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();

修复:BuildPredicate可以在没有动态的情况下写入. BuildPredicate示例代码已更改.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读