Generic按相关对象排序

时间:2016-05-06 10:11:55

标签: c# entity-framework linq sorting expression

我正在使用Cincura先生(http://blog.cincura.net/229310-sorting-in-iqueryable-using-string-as-column-name/)的这个伟大的通用排序助手来排序使用Entity Framework从SQL Server返回的记录

 private static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel)
    {
        ParameterExpression param = Expression.Parameter(typeof(T), string.Empty); // I don't care about some naming
        MemberExpression property = Expression.PropertyOrField(param, propertyName);
        LambdaExpression sort = Expression.Lambda(property, param);
        MethodCallExpression call = Expression.Call(
            typeof(Queryable),
            (!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty),
            new[] { typeof(T), property.Type },
            source.Expression,
            Expression.Quote(sort));
        return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(call);
    }

问题是它可以从对象的任何属性起作用,但不能用于相关对象的属性。如果我有

public foo FOO;

public class foo
        {
            public string name {get;set};
            public bar Bar {get;set;}

    }

    public class bar
    {
        public string name {get;set;}
    }

我可以按 FOO.name 排序,但不能按 FOO.Bar.name 排序,但不能按foo.Bar.name排序。

我想我必须联系另一个表达,但到目前为止我的尝试都没有结果。我将不胜感激任何帮助。

3 个答案:

答案 0 :(得分:1)

您必须自己构建嵌套成员表达式,例如,通过拆分propertyName-parameter并循环遍历它:

public static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel)
{
    ParameterExpression param = Expression.Parameter(typeof(T), string.Empty); // I don't care about some naming

    Expression body = param;
    foreach (var member in propertyName.Split('.'))
    {
        body = Expression.PropertyOrField(body, member);
    }

    LambdaExpression sort = Expression.Lambda(body, param);
    MethodCallExpression call = Expression.Call(
        typeof(Queryable),
        (!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty),
        new[] { typeof(T), body.Type },
        source.Expression,
        Expression.Quote(sort));

    return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(call);
}

答案 1 :(得分:0)

使酒吧具有可比性

    public class bar : IComparable
    {
        public string name { get; set; }

        public int CompareTo(object other)
        {
            return this.name.CompareTo(((bar)other).name);
        }
    }

答案 2 :(得分:0)

为了支持属性路径,请替换

MemberExpression property = Expression.PropertyOrField(param, propertyName);

var property = propertyName.Split('.').Aggregate((Expression)param, Expression.PropertyOrField);