为通用列表创建排序函数

3

我有一种方法可以通过对象字段对通用列表进行排序:

public static IQueryable<T> SortTable<T>(IQueryable<T> q, string sortfield, bool ascending)
{
    var p = Expression.Parameter(typeof(T), "p");

    if (typeof(T).GetProperty(sortfield).PropertyType == typeof(int?))
    {
        var x = Expression.Lambda<Func<T, int?>>(Expression.Property(p, sortfield), p);
        if (ascending)
            q = q.OrderBy(x);
        else
            q = q.OrderByDescending(x);
    }
    else if (typeof(T).GetProperty(sortfield).PropertyType == typeof(int))
    {
        var x = Expression.Lambda<Func<T, int>>(Expression.Property(p, sortfield), p);
        if (ascending)
            q = q.OrderBy(x);
        else
            q = q.OrderByDescending(x);
    }
    else if (typeof(T).GetProperty(sortfield).PropertyType == typeof(DateTime))
    {
        var x = Expression.Lambda<Func<T, DateTime>>(Expression.Property(p, sortfield), p);
        if (ascending)
            q = q.OrderBy(x);
        else
            q = q.OrderByDescending(x);
    }
    // many more for every type
    return q;
}

有没有办法将这些if语句合并为一个通用语句? 主要问题在于对于部分Expression.Lambda<Func<T, int>>,我不确定如何编写通用代码。


https://dev59.com/nnVD5IYBdhLWcg3wQJKT - Marc Gravell
2个回答

3

如果您展开Queryable.OrderBy到其定义,那么您就不必使用Expression.Lambda的泛型重载:

public static IQueryable<T> SortTable<T>(
    IQueryable<T> q, string sortfield, bool ascending)
{
    var p = Expression.Parameter(typeof(T), "p");
    var x = Expression.Lambda(Expression.Property(p, sortfield), p);

    return q.Provider.CreateQuery<T>(
               Expression.Call(typeof(Queryable),
                               ascending ? "OrderBy" : "OrderByDescending",
                               new Type[] { q.ElementType, x.Body.Type },
                               q.Expression,
                               x));
}

0

这个行不行?

    public static IQueryable<T> SortTable<T>(IQueryable<T> q, string sortfield, bool ascending)
    {
        var type = typeof(T).GetProperty(sortfield).PropertyType;
        var p = Expression.Parameter(typeof(T), "p");
        var x = Expression.Lambda<Func<T, type> >(Expression.Property(p, sortfield), p);
        if (ascending)
            q = q.OrderBy(x);
        else
            q = q.OrderByDescending(x);
        return q;
    }

type 不是一个类型变量(如 T),所以这样做行不通。 - dtb
在System.Reflection中有一个方法可以返回Func<T, type>类型,但是我相信... - Noldorin
@Noldorin:你是指 typeof(Func<,>).MakeGenericType(typeof(T), type) 吗?但是这样你仍然不能使用结果来调用 Expression.Lambda<X> 而不使用反射。 - dtb
我仍在使用.NET 2.0 =D。谢谢大家! - Nayan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接