LINQ - OrderBy的动态表达式

Hol*_*loW 2 linq asp.net-mvc entity-framework

我有一点问题,我会试着详细解释一下.

在我的系统上,我有一个使用EF 4.1的通用存储库.一切都很棒,但我在某种情况下遇到问题我需要通过一些查询来做动态排序.

我通过参数接收一个表示我班级字段的"字符串"来执行orderBy(如"id"或"description")

部分代码:

        public class SomeClass
        {
            public int id { get; set; }
            public string description { get; set; }
        }

        // First we define the parameter that we are going to use
        // in our OrderBy clause. This is the same as "(parameter =>"
        // in the example above.
        var param = Expression.Parameter(typeof(SomeClass), "parameter");

        // Now we'll make our lambda function that returns the
        // request.SortingName property by it's name.
        var expression = Expression.Lambda<Func<SomeClass, int>>(Expression.Property(param, request.SortingName), param);
Run Code Online (Sandbox Code Playgroud)

好吧,如果"request.SortingName"类型为"int"(id),则此代码有效,但如果我想通过"string"(描述)或其他类型生成orderBy,则此代码不起作用.

我将表达式更改为使用"object":

        var expression = Expression.Lambda<Func<SomeClass, object>>(Expression.Property(param, request.SortingName), param);
Run Code Online (Sandbox Code Playgroud)

但是当我运行代码时,编译器会抛出下一个异常:'System.Int32'类型的表达式不能用于返回类型'System.Object'

如果属性是字符串类型,则异常为"System.String"类型的表达式不能用于返回类型"System.Object"

换句话说,代码不适用于"对象"类型.

任何人都知道如何解决这个问题?

谢谢你的时间.

Rob*_*Rob 6

以下是我使用EF4和我在标准开发库中创建的一些通用方法进行动态排序和分页的方法.重要的是您用于为SortBy方法创建Lambda表达式的第二部分代码.

public enum SqlOrderByDirecton
{
    ASC,
    DESC
}
Run Code Online (Sandbox Code Playgroud)
 //Derive Lambda Expression from string

 string sortByKey = "BusinessId";
 string value = "DESC";

 var p = Expression.Parameter(typeof(T));

 this.SortBy = Expression.Lambda<Func<T, dynamic>>(Expression.TypeAs(Expression.Property(p, sortByKey), typeof(object)), p).Compile();

 this.SortOrder = (DevCore.SqlOrderByDirecton)Enum.Parse(typeof(DevCore.SqlOrderByDirecton), value, true);
Run Code Online (Sandbox Code Playgroud)
public static List<T> SortAndPaginate<T>(IEnumerable<T> query,
                                             Func<T, object> sortBy,
                                             SqlOrderByDirecton sortOrder,
                                             int rowLimit,
                                             int startRecord,
                                             out int recordCount)
    {
        recordCount = query.Count();

        List<T> list = new List<T>();

        if (sortOrder == SqlOrderByDirecton.ASC)
        {
            list = query.OrderBy(sortBy).Skip(startRecord).Take(rowLimit).ToList();
        }
        else
        {
            list = query.OrderByDescending(sortBy).Skip(startRecord).Take(rowLimit).ToList();
        }

        return list;
    }
Run Code Online (Sandbox Code Playgroud)