表达式树+反射实现动态排序。List动态排序,集合动态排序

比如要点击表头进行排序,排序的字段比如多,一个一个判断去写就比较麻烦。判断就太多了,如果其他地方也要用排序重复代码就会很多,类似这种。

if (sort.ToLower() == "max")
{
    if (sortway == "asc")
    {
        query = query.OrderBy(a => a.Max);
    }
    else
    {
        query = query.OrderByDescending(a => a.Max);
    }
}
if (sort.ToLower() == "min")
{
    if (sortway == "asc")
    {
        query = query.OrderBy(a => a.Min);
    }
    else
    {
        query = query.OrderByDescending(a => a.Min);
    }
}
if (sort.ToLower() == "sum")
{
    if (sortway == "asc")
    {
        query = query.OrderBy(a => a.Min);
    }
    else
    {
        query = query.OrderByDescending(a => a.Min);
    }
}

所以我们封装一下通用的排序方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SmartEDU.LabRoom.Service.Tools
{
    /// <summary>
    /// AJ:集合动态排序工具类
    /// </summary>
    public static class OrderTools
    {
        public static IEnumerable<TSource> OrderByStr<TSource>(this IEnumerable<TSource> query, string sort, string sortway)
        {
            if (!string.IsNullOrEmpty(sort))
            {
                //第一步要拿到排序字段的类型。忽略大小写一下
                Type propertyType = typeof(TSource).GetProperty(sort, BindingFlags.Public|BindingFlags.IgnoreCase|BindingFlags.Instance).PropertyType;
                //通过反射拿到方法
                var method = typeof(OrderTools).GetMethod(sortway == "asc" ? "DealAsc" : "DealDesc");
                //给反射拿到的方法提供泛型
                method = method.MakeGenericMethod(typeof(TSource), propertyType);
                //反射调用方法
                IEnumerable<TSource> result = (IEnumerable<TSource>)method.Invoke(null, new object[] { query, sort });
                return result;
            }
            return query;
        }
        /// <summary>
        /// 处理升序排序
        /// 通过一个方法中转实现类型的传递
        /// </summary>
        public static IEnumerable<TSource> DealAsc<TSource, M>(IEnumerable<TSource> query, string sort)
        {
            return query.OrderBy(OrderLamdba<TSource, M>(query, sort).Compile());
        }
        /// <summary>
        /// 处理降序排序
        /// 通过一个方法中转实现类型的传递
        /// </summary>
        public static IEnumerable<TSource> DealDesc<TSource, M>(IEnumerable<TSource> query, string sort)
        {
            return query.OrderByDescending(OrderLamdba<TSource, M>(query, sort).Compile());
        }
        static Expression<Func<TSource, M>> OrderLamdba<TSource, M>(IEnumerable<TSource> query, string sort)
        {
            var left = Expression.Parameter(typeof(TSource), "a");
            var body = Expression.Property(left, sort);
            Expression<Func<TSource, M>> lamdba = Expression.Lambda<Func<TSource, M>>(body, left);
            return lamdba;
        }
    }
}

使用就很方便了

//降序
if (item.IsDesc)
{
    labStatisticsList = labStatisticsList.OrderByStr(item.OrderField, "desc").ToList();
}
//升序
else 
{
    labStatisticsList = labStatisticsList.OrderByStr(item.OrderField, "asc").ToList();
}

这里升序降序其实都可以不用判断,按照升降序的格式传递就行,我这里是修改同事写的代码,前台传递过来就是这种格式了。

你可能感兴趣的