3

I have a method for sorting generic lists by the object fields:

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;
}

Is there any way I can collapse those ifs to a single generic statement? The main problem is that for the part Expression.Lambda<Func<T, int>> I am not sure how to write it generically.

1

2 Answers 2

3

If you expand Queryable.OrderBy to its definition then you don't have to use the generic overload of 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));
}
Sign up to request clarification or add additional context in comments.

Comments

0

Won't this work?

    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;
    }

3 Comments

type is not a type variable (like T), so this won't work.
There is a method in System.Reflection that can return the Func<T, type> type, however, I beleieve...
@Noldorin: Do you mean typeof(Func<,>).MakeGenericType(typeof(T), type)? But then you still cannot use the result to invoke Expression.Lambda<X> without reflection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.