陪你听风

表达式树+反射+扩展方法实现动态排序效果

电脑版发表于: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


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

关于TNBLOG
TNBLOG,技术分享。技术交流:群号677373950
ICP备案 :渝ICP备18016597号-1
App store Android
精彩评论
{{item.replyName}}
{{item.content}}
{{item.time}}
{{subpj.replyName}}
@{{subpj.beReplyName}}{{subpj.content}}
{{subpj.time}}
猜你喜欢