tnblog
首页
视频
资源
登录

EF扩展反射实现动态排序+表达式树

3937人阅读 2019/10/23 17:29 总访问:93865 评论:0 收藏:1 手机
分类: .NET MVC

现在各种网站上的表格可以通过点击排头来实现排序

例如:


今天我就来一探究竟,这是怎么实现的呢?



具体步骤:

    我通过写扩展方法的方式来实现的,扩展EF。当然我们得写一个灵活性强的,支持多种类型的,通过反射来实行中转,我们反射调用方法的时候可以动态传递类型。


定义一个静态方法,参数:sort(排序的字段),sortway(排序方式)

public static IQueryable<TSource> MyOrderBy<TSource>(this IQueryable<TSource> source, string sort, string sortway)
{
        
}


1、获取排序字段的类型

//首先要拿到排序字段的类型
Type type = typeof(TSource).GetProperty(sort).PropertyType;


2、把处理升序和降序、生成Lamdba表达式的方法提出来写

    

        /// <summary>
        /// 处理升序的方法
        /// </summary>
        public static IQueryable<TSource> DealAsc<TSource, M>(this IQueryable<TSource> source, string sort)
        {
            //生成lamdba表达式
            Expression<Func<TSource, M>> lamdba = CreateLamdba<TSource, M>(source, sort);

            source = source.OrderBy(lamdba);
            return source;
        }

        /// <summary>
        /// 处理降序的方法
        /// </summary>
        public static IQueryable<TSource> DealDesc<TSource, M>(this IQueryable<TSource> source, string sort)
        {
            //生成lamdba表达式
            Expression<Func<TSource, M>> lamdba = CreateLamdba<TSource, M>(source, sort);

            source = source.OrderByDescending(lamdba);

            return source;
        }

        /// <summary>
        /// 生成Lamdba表达式
        /// </summary>
        static Expression<Func<TSource, M>> CreateLamdba<TSource, M>(this IQueryable<TSource> source, string sort)
        {
            var parame = Expression.Parameter(typeof(TSource), "a");
            var body = Expression.Property(parame, sort);
            //生成lamdba表达式
            Expression<Func<TSource, M>> lamdba = Expression.Lambda<Func<TSource, M>>(body, parame);

            return lamdba;
        }

3、通过反射来调用方法,因为这样可以动态传递类型,如果直接调用不能动态传递类型,只能指定类型

    1)先通过反射拿到方法,并且判断排序方式调用对应的方法

    var mothed = typeof(MyTools).GetMethod(sortway=="asc"? "DealAsc":"DealDesc");

    2)最关键的一步,给方法指定类型

      mothed = mothed.MakeGenericMethod(typeof(TSource), type);

    3)调用方法

        IQueryable<TSource> result = (IQueryable<TSource>)mothed.Invoke(null, new object[] { source, sort });


下面奉上完整代码:

public static class MyTools
    {
        public static IQueryable<TSource> MyOrderBy<TSource>(this IQueryable<TSource> source, string sort, string sortway)
        {
            if (!string.IsNullOrEmpty(sort))
            {
                //首先要拿到排序字段的类型
                Type type = typeof(TSource).GetProperty(sort).PropertyType;
                //如果直接调用处理升序或者降序的方法,参数类型还是无法传递过来
                //例如:DealAsc(TSource,type);
                //虽然type取到的是参数类型,但是type作为变量,不能直接传递过去
                //所以,我们可以用反射调用方法来实现,这样可以动态传递参数类型
                //1、先用反射拿到方法
                var mothed = typeof(MyTools).GetMethod(sortway=="asc"? "DealAsc":"DealDesc");
                //2、给方法传递类型
                mothed = mothed.MakeGenericMethod(typeof(TSource), type);
                //3、调用方法
                IQueryable<TSource> result = (IQueryable<TSource>)mothed.Invoke(null, new object[] { source, sort });
                return result;
            }
            return source;
        }
        /// <summary>
        /// 处理升序的方法
        /// </summary>
        public static IQueryable<TSource> DealAsc<TSource, M>(this IQueryable<TSource> source, string sort)
        {
            //生成lamdba表达式
            Expression<Func<TSource, M>> lamdba = CreateLamdba<TSource, M>(source, sort);
            source = source.OrderBy(lamdba);
            return source;
        }
        /// <summary>
        /// 处理降序的方法
        /// </summary>
        public static IQueryable<TSource> DealDesc<TSource, M>(this IQueryable<TSource> source, string sort)
        {
            //生成lamdba表达式
            Expression<Func<TSource, M>> lamdba = CreateLamdba<TSource, M>(source, sort);
            source = source.OrderByDescending(lamdba);
            return source;
        }
        /// <summary>
        /// 生成Lamdba表达式
        /// </summary>
        static Expression<Func<TSource, M>> CreateLamdba<TSource, M>(this IQueryable<TSource> source, string sort)
        {
            var parame = Expression.Parameter(typeof(TSource), "a");
            var body = Expression.Property(parame, sort);
            //生成lamdba表达式
            Expression<Func<TSource, M>> lamdba = Expression.Lambda<Func<TSource, M>>(body, parame);
            return lamdba;
        }
    }


调用就很简单了,直接点出来就行


学了这一招,妈妈再也不用担心我的类型传不了了!

评价
网络上你重拳出击,现实中你刚上初一
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
欢迎加群交流技术