首页 > 解决方案 > 使用表达式树生成排序列表

问题描述

我有一个 IQueryable 类型的集合,我需要根据一些动态排序字段对其进行排序。排序字段位于列表中。

我编写了以下方法来做到这一点。

public List<T> Order<T>(IQueryable<T> source, List<string> propertyNames)
    {

        if(propertyNames != null && propertyNames.Count > 0)
        {
            var param = Expression.Parameter(typeof(T), string.Empty);
            var property = Expression.PropertyOrField(param, propertyNames[0]);

            var sort = Expression.Lambda(property, param);
            MethodCallExpression orderByCall = Expression.Call(typeof(Queryable),"OrderBy",new[] { property.Type },Expression.Quote(sort));
            if(propertyNames.Count > 1)
            {
                foreach(var item in propertyNames)
                {
                    param = Expression.Parameter(typeof(T), string.Empty);
                    property = Expression.PropertyOrField(param, item);

                    sort = Expression.Lambda(property, param);

                    orderByCall = Expression.Call(
                        typeof(Queryable),
                        "ThenBy", new[] { typeof(T), property.Type },
                        orderByCall,
                        Expression.Quote(sort));
                }
            }

            var results = (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(orderByCall);
            if(results != null)
             return results.ToList();

        }

        return null;
    }

当我执行时, MethodCallExpression orderByCall = Expression.Call(typeof(Queryable),"OrderBy",new[] { property.Type },Expression.Quote(sort));我遇到了一些异常

类型“System.Linq.Queryable”上没有通用方法“OrderBy”与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。

标签: c#.netlinq

解决方案


抱歉,我没有针对您的错误的直接解决方案。

这是动态排序数据的替代方法(“保持简单”)。

1)在项目的某处添加这些扩展方法

public static IOrderedQueryable<TSource> OrderBy<TSource, TProperty>(this IQueryable<TSource> source
      , Expression<Func<TSource, TProperty>> expression, bool descending)
{
      return !descending ? source.OrderBy(expression) : source.OrderByDescending(expression);
}

public static IOrderedQueryable<TSource> ThenBy<TSource, TProperty>(this IOrderedQueryable<TSource> source
  , Expression<Func<TSource, TProperty>> expression, bool descending)
{
  return !descending ? source.ThenBy(expression) : source.ThenByDescending(expression);
}

2)现在您可以循环您的属性名称列表并在您的 IQueryable 上应用 OrderBy / ThenBy。

其他想法:您可以调整您的方法,使其接受表达式而不是属性名称字符串。


推荐阅读