表达式树+反射+扩展方法实现动态排序效果
电脑版发表于:2019/10/23 18:44
后台代码如下:
方法1:逐个判断 -->缺点:代码重复,体验感差
if (sort.ToLower() == "max") { if (sortway == "asc") { query2=query2.OrderBy(a => a.max); } else { query2=query2.OrderByDescending(a => a.max); } } if (sort.ToLower() == "min") { if (sortway == "asc") { query2 = query2.OrderBy(a => a.min); } else { query2 = query2.OrderByDescending(a => a.min); } }
方法2:缺点:参数类型固定的,对于不同类型排序时会报错
if (!string.IsNullOrWhiteSpace(sort)) { //反射获取属性 var method = sort.GetType().GetProperties(); //定义表达式树中的参数 var left = Expression.Parameter(typeof(AllScoreModel), "a"); //创造一个表示访问属性的Expression(表达式树) var body = Expression.Property(left, sort); //得到lamdba表达式 Expression<Func<AllScoreModel, int?>> lamdba = Expression.Lambda<Func<AllScoreModel, int?>>(body, left); //此时的lamdba自动组合为:a=>a.sort形式,sort为传的值 if (sortway == "asc") { query2 = query2.OrderBy(lamdba); } else { query2 = query2.OrderByDescending(lamdba); } }
我们现在写的动态排序只支持int类型,如果是小数类型排序就会报错,比如根据平均分排序
所以这里我们不能写死。这里就需要动态的获取属性类型,可以巧妙的使用反射方法来中转,因为反射调用方法的时候可以传递类型参数
//方法3,扩展方法封装使用,然后linq语句或lamdba语句后面调用OrderBy(sort,sortway)传参即可
//sort(排序的字段),sortway(排序的方式)
//新建一个类,封装MyOrderBy扩展方法
public static class MyExpressionoderby { //封装自动升序或者降序的排序,解决不同类型的转换问题 public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> query, string sort, string sortway) { if (!string.IsNullOrWhiteSpace(sort)) { //第一步,拿到排序字段的类型 Type propertyType = typeof(TSource).GetProperty(sort).PropertyType; //如果直接调用方法,参数类型还是无法转换 //反射调用方法,可以动态传递类型 //通过反射,拿到方法 var method = typeof(MyExpressionoderby).GetMethod(sortway == "asc" ? "DealAsc" : "DealDesc"); //给反射拿到的方法提供泛型,需要现得到对象(method),再取出去调用 //否则报错:
不能对 ContainsGenericParameters 为 True 的类型或方法执行后期绑定操作。
method = method.MakeGenericMethod(typeof(TSource), propertyType); //MakeGenericMethod:泛型,参数变量 //反射调用方法 IQueryable<TSource> result = (IQueryable<TSource>)method.Invoke(null, new object[] { query, sort }); //Invoke(null, new object[] { query, sort })反射对象语句 return result; } return query; } /// <summary> /// 处理升序排序 /// 通过一个方法中转实现类型的传递 /// </summary> public static IQueryable<TSource> DealAsc<TSource, M>(IQueryable<TSource> query, string sort) { var left = Expression.Parameter(typeof(TSource), "a"); var body = Expression.Property(left, sort); //此时的lamdba自动组合为:a=>a.sort形式,sort为传的值 Expression<Func<TSource, M>> lamdba = Expression.Lambda<Func<TSource, M>>(body, left); query = query.OrderBy(lamdba); return query; } /// <summary> /// 处理降排序 /// 通过一个方法中转实现类型的传递 /// </summary> public static IQueryable<TSource> DealDesc<TSource, M>(IQueryable<TSource> query, string sort) { var left = Expression.Parameter(typeof(TSource), "a"); var body = Expression.Property(left, sort); //此时的lamdba自动组合为:a=>a.sort形式,sort为传的值 Expression<Func<TSource, M>> lamdba = Expression.Lambda<Func<TSource, M>>(body, left); query = query.OrderByDescending(lamdba); return query; } }
使用的时候很简单在后面直接点出来就好
对于前台的话,就需要自定义属性传值:图如下:
前台最后一步神奇就是js传值和动态改变排序啦:
好了,效果完成,完美的动态排序就完成了 hahaha
以上为市场最昂贵的干货啦,觉得喜欢的朋友可以收藏一份哦