使用表达式树生成排序列表

时间:2018-12-17 07:50:06

标签: c# .net linq

我有一个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'是   与提供的类型实参和实参兼容。没有类型   如果该方法是非泛型的,则应提供参数。

1 个答案:

答案 0 :(得分:1)

对不起,我没有直接解决您的错误的方法。

这里是动态排序数据的另一种方法(“保持简单”)。

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。

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