使用反射可以实现这个吗?

4

可能是重复问题:
动态LINQ排序

我有一个自定义排序选项列表,这些选项是从客户端网格控件(如果您好奇的话是KendoUI网格)传递到服务器的。这些排序选项具有按字符串排序的属性。我编写了一个 switch 方法,将检查排序对象的值并应用适当的LINQ。

    private IQueryable<Report> SortReports(IQueryable<Report> reports, KendoSort sort)
    {
        switch (sort.Field)
        {
            case "name":
                return sort.Dir == "asc" ? reports.OrderBy(x => x.Name) : reports.OrderByDescending(x => x.Name);
            case "description":
                return sort.Dir == "asc" ? reports.OrderBy(x => x.Description) : reports.OrderByDescending(x => x.Description);
            default:
                return sort.Dir == "asc" ? reports.OrderBy(x => x.Id) : reports.OrderByDescending(x => x.Id);
        }
    }

这个功能可以正常使用,但是看起来很丑。我该如何使用反射来做到这一点,以便我不必为我想要执行此操作的每种类型的实体编写自定义函数?如果我能有一个单独的函数,无论实体是什么,都可以执行此操作,那就太好了。


我不明白反射在这里有什么作用,但你可以通过枚举类型来替换你的字符串。 - LightStriker
动态LINQ OrderBy - L.B
4个回答

2
你可以使用动态 LINQ。这是一篇来自 Scott Gu 的博客文章,你可以在这里查看:blog post

很棒的解决方案。我不确定我更喜欢哪一个! - Chev
你刚刚让我的生活变得轻松了许多。在存储库方法中执行以下操作:foreach (var sort in kendoSorts) reports = reports.OrderBy(string.Format("{0} {1}", sort.Field, sort.Dir)); foreach循环允许它处理多个排序。 - Chev

1
Marc Gravell有一个非常棒的小库叫做FastMember。你可以像这样使用它:
private IQueryable<Report> SortReports(IQueryable<Report> reports,KendoSort sort)
{
    var accessor = TypeAccessor.Create(typeof(Report));
    return sort.Dir == "asc" ? 
        reports.OrderBy(x => accessor[x,sort.Field]) : 
        reports.OrderByDescending(x => accessor[x,sort.Field]));
}

不错!如果我将这个方法泛型化,我就可以交换“Report”并用于任何集合了。完美。 - Chev
是的,那应该很好用。 - Eren Ersönmez

1
使用反射,其中 KendoSort.Property 是报表属性的 PropertyInfo,返回需要排序的值。
private IQueryable<Report> SortReports(IQueryable<Report> reports, KendoSort sort)
{
    return sort.Dir == "asc" ? reports.OrderBy(x => sort.Property.GetValue(x)) : reports.OrderByDescending(x => sort.Property.GetValue(x));
}

然而,反射相对较慢。其他解决方案可能更好。


+1 因为回答了我的确切问题,尽管最终反射并不是我想要的 :) - Chev

1
以下代码可以动态创建您所需的排序函数。
ParameterExpression pe = Expression.Parameter(typeof(Report), "x");
LambdaExpression le = Expression.Lambda(
    Expression.PropertyOrField(pe, sort.Field),
    new List<ParameterExpression>() {pe});

var leCompiled = (Func<Report, string>)le.Compile();                

return sort.Dir == "asc" ? reports.OrderBy(leCompiled) : reports.OrderByDescending(leCompiled);

它创建了一个 Func 委托,其形式为 x => x.ReportProperty,其中 ReportProperty 是 sort.Field 的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接