Is it possible to do this with reflection?
本问题已经有最佳答案,请猛点这里访问。
Possible Duplicate:
Dynamic LINQ OrderBy
我有一个自定义排序选项列表,这些选项通过客户端网格控件(如果您想知道,可以使用Kendoui网格)传递给服务器。这些排序选项具有作为字符串排序的属性。我编写了一个switch方法,它将检查sort对象的值并应用适当的linq。
1 2 3 4 5 6 7 8 9 10 11 12 | 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); } } |
这很管用,但看起来很难看。我如何利用反射来实现这一点,这样就不必为每种类型的实体编写自定义函数了?如果我能有一个单独的函数,不管实体是什么,都能做到这一点,那就太好了。
您可以使用动态LINQ。这是顾司各特写的一篇关于它的文章。
下面应该创建动态需要的排序函数。
1 2 3 4 5 6 7 8 | 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); |
它以x=>x.reportproperty的形式创建了一个func委托,其中reportproperty是sort.field的值。
使用反射,其中kendosort.property是返回排序所需值的报表属性的propertyinfo。
1 2 3 4 | 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)); } |
但是,反射速度相对较慢。其他解决方案可能更好。
MarcGravell有一个叫做FastMember的伟大的小图书馆。您可以这样使用它:
1 2 3 4 5 6 7 | 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])); } |