为OrderBy组合Lambda表达式

时间:2016-10-25 16:08:23

标签: c# asp.net-mvc lambda

我正在尝试使用多列来排序查询。以下是我的代码和参数值。它在我尝试添加两个带有错误的表达式的行中失败:

  

没有为类型'System.String'定义二元运算符Add   和'System.Single'。

非常感谢任何帮助!!

sortColumn = "table1.column1,table2.column1,column3"

public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string sortColumn, string direction) {
    string methodName = string.Format("OrderBy{0}", direction.ToLower() == "asc" ? "" : "descending");
    ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");
    MemberExpression memberAccess = null;
    LambdaExpression orderByLambda = null;

    foreach (var fields in sortColumn.Split(',')) {
        memberAccess = null;
        foreach (var property in fields.Split('.')) {
            memberAccess = MemberExpression.Property(memberAccess ?? (parameter as Expression), property);
        } if (orderByLambda == null) {
            orderByLambda = Expression.Lambda(memberAccess, parameter);
        } else {
            orderByLambda = Expression.Lambda(Expression.Add(orderByLambda.Body, Expression.Lambda(Expression.Invoke(Expression.Lambda(memberAccess, parameter), parameter), parameter).Body), parameter);
        }
    }
    MethodCallExpression result = Expression.Call(
              typeof(Queryable),
              methodName,
              new[] { query.ElementType, memberAccess.Type },
              query.Expression,
              Expression.Quote(orderByLambda));
    return query.Provider.CreateQuery<T>(result);
}

1 个答案:

答案 0 :(得分:1)

您需要在外层使用OrderBy / ThenBy链接表达式,而不是内层。方法如下:

public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string sortColumn, string direction) {
    var methodNameFirst = string.Format("OrderBy{0}", direction.ToLower() == "asc" ? "" : "descending");
    var methodNameContinue = string.Format("ThenBy{0}", direction.ToLower() == "asc" ? "" : "descending");
    ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");
    Expression result = query.Expression;
    var methodName = methodNameFirst;
    foreach (var fields in sortColumn.Split(',')) {
        Expression memberAccess = null;
        foreach (var property in fields.Split('.')) {
            memberAccess = MemberExpression.Property(memberAccess ?? (parameter as Expression), property);
        }
        LambdaExpression orderByLambda = Expression.Lambda(memberAccess, parameter);
        result = Expression.Call(
            typeof(Queryable),
            methodName,
            new[] { query.ElementType, memberAccess.Type },
            result,
            Expression.Quote(orderByLambda));
        methodName = methodNameContinue;
    }
    return query.Provider.CreateQuery<T>(result);
}