表达式树+反射+扩展方法实现动态排序效果
电脑版发表于: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


以上为市场最昂贵的干货啦,觉得喜欢的朋友可以收藏一份哦
