【问题标题】:Creating a sort function for a generic list为通用列表创建排序函数
【发布时间】:2010-04-15 15:34:16
【问题描述】:

我有一种按对象字段对通用列表进行排序的方法:

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&lt;Func&lt;T, int&gt;&gt; 我不知道如何通用地写它。

【问题讨论】:

标签: c# generics


【解决方案1】:

如果您将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));
}

【讨论】:

    【解决方案2】:

    这不行吗?

        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),所以这不起作用。
    • System.Reflection 中有一个方法可以返回Func&lt;T, type&gt; 类型,但是,我相信...
    • @Noldorin:你的意思是typeof(Func&lt;,&gt;).MakeGenericType(typeof(T), type)?但是你仍然不能使用结果来调用Expression.Lambda&lt;X&gt;而不进行反射。
    • 我仍在使用 .NET 2.0 =D。谢谢大家!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 2015-07-11
    • 1970-01-01
    相关资源
    最近更新 更多