I'm searching a way to store a collection of Expression<Func<T, TProperty>> used to order elements, and then to execute the stored list against a IQueryable<T> object (the underlying provider is Entity Framework).  
For example, I would like to do something like this (this is pseudo code):
public class Program
{
    public static void Main(string[] args)
    {
        OrderClause<User> orderBys = new OrderClause<User>();
        orderBys.AddOrderBy(u => u.Firstname);
        orderBys.AddOrderBy(u => u.Lastname);
        orderBys.AddOrderBy(u => u.Age);
        Repository<User> userRepository = new Repository<User>();
        IEnumerable<User> result = userRepository.Query(orderBys.OrderByClauses);
    }
}
An order by clause (property on which to order):
public class OrderClause<T>
{
    public void AddOrderBy<TProperty>(Expression<Func<T, TProperty>> orderBySelector)
    {
        _list.Add(orderBySelector);
    }
    public IEnumerable<Expression<Func<T, ???>>> OrderByClauses
    {
        get { return _list; }
    }
}
A repository with my query method:
public class Repository<T>
{
    public IEnumerable<T> Query(IEnumerable<OrderClause<T>> clauses)
    {
        foreach (OrderClause<T, ???> clause in clauses)
        {
            _query = _query.OrderBy(clause);
        }
        return _query.ToList();
    }
}
My first idea was to convert the Expression<Func<T, TProperty>> into a string (the property name on which to sort). So basically, instead of storing a typed list (which is not possible because the TProperty is not constant), I store a list of string with the properties to sort on.
But this doesn't work because then I cannot reconstruct the Expression back (I need it because IQueryable.OrderBy takes a Expression<Func<T, TKey>> as parameter). 
I also tried to dynamically create the Expression (with the help of Expression.Convert), to have a Expression<Func<T, object>> but then I got an exception from entity framework that said that it was not able to handle the Expression.Convert statement.
If possible, I do not want to use an external library like the Dynamic Linq Library.
This is one of the few cases where a dynamic / reflection solution may be appropriate.
I think you want something like this? (I've read between the lines and made some changes to your structure where I thought necessary).
public class OrderClauseList<T>
{
    private readonly List<LambdaExpression> _list = new List<LambdaExpression>();
    public void AddOrderBy<TProperty>(Expression<Func<T, TProperty>> orderBySelector)
    {
        _list.Add(orderBySelector);
    }
    public IEnumerable<LambdaExpression> OrderByClauses
    {
        get { return _list; }
    }
}
public class Repository<T>
{
    private IQueryable<T> _source = ... // Don't know how this works
    public IEnumerable<T> Query(OrderClause<T> clauseList)
    {
        // Needs validation, e.g. null-reference or empty clause-list. 
        var clauses = clauseList.OrderByClauses;
        IOrderedQueryable<T> result = Queryable.OrderBy(_source, 
                                                        (dynamic)clauses.First());
        foreach (var clause in clauses.Skip(1))
        {
            result = Queryable.ThenBy(result, (dynamic)clause);
        }
        return result.ToList();
    }
}
The key trick is getting C# dynamic to do the horrible overload resolution and type-inference for us. What's more, I believe the above, despite the use of dynamic, is actually type-safe!
One way to do this would be to “store” all the sort clauses in something like Func<IQueryable<T>, IOrderedQueryable<T>> (that is, a function that calls the sorting methods):
public class OrderClause<T>
{
    private Func<IQueryable<T>, IOrderedQueryable<T>> m_orderingFunction;
    public void AddOrderBy<TProperty>(Expression<Func<T, TProperty>> orderBySelector)
    {
        if (m_orderingFunction == null)
        {
            m_orderingFunction = q => q.OrderBy(orderBySelector);
        }
        else
        {
            // required so that m_orderingFunction doesn't reference itself
            var orderingFunction = m_orderingFunction;
            m_orderingFunction = q => orderingFunction(q).ThenBy(orderBySelector);
        }
    }
    public IQueryable<T> Order(IQueryable<T> source)
    {
        if (m_orderingFunction == null)
            return source;
        return m_orderingFunction(source);
    }
}
This way, you don't have to deal with reflection or dynamic, all this code is type safe and relatively easy to understand.
You can store your lambda expressions in a collection as instances of the LambdaExpression type.
Or even better, store sort definitions, each of which, in addition to an expression, aslo stores a sorting direction.
Suppose you have the following extension method
public static IQueryable<T> OrderBy<T>(
    this IQueryable<T> source,
    SortDefinition sortDefinition) where T : class
{
    MethodInfo method;
    Type sortKeyType = sortDefinition.Expression.ReturnType;
    if (sortDefinition.Direction == SortDirection.Ascending)
    {
        method = MethodHelper.OrderBy.MakeGenericMethod(
            typeof(T),
            sortKeyType);
    }
    else
    {
        method = MethodHelper.OrderByDescending.MakeGenericMethod(
            typeof(T),
            sortKeyType);
    }
    var result = (IQueryable<T>)method.Invoke(
        null,
        new object[] { source, sortDefinition.Expression });
    return result;
}
and a similar method for ThenBy. Then you can do something like
myQueryable = myQueryable.OrderBy(sortDefinitions.First());
myQueryable = sortDefinitions.Skip(1).Aggregate(
   myQueryable,
   (current, sortDefinition) => current.ThenBy(sortDefinition));
Here are the definitions of SortDefinition and MethodHelper
public class SortDefinition
{
    public SortDirection Direction
    {
        get;
        set;
    }
    public LambdaExpression Expression
    {
        get;
        set;
    }
}
internal static class MethodHelper
{
    static MethodHelper()
    {
        OrderBy = GetOrderByMethod();
        ThenBy = GetThenByMethod();
        OrderByDescending = GetOrderByDescendingMethod();
        ThenByDescending = GetThenByDescendingMethod();
    }
    public static MethodInfo OrderBy
    {
        get;
        private set;
    }
    public static MethodInfo ThenBy
    {
        get;
        private set;
    }
    public static MethodInfo OrderByDescending
    {
        get;
        private set;
    }
    public static MethodInfo ThenByDescending
    {
        get;
        private set;
    }
    private static MethodInfo GetOrderByMethod()
    {
        Expression<Func<IQueryable<object>, IOrderedQueryable<object>>> expr =
            q => q.OrderBy((Expression<Func<object, object>>)null);
        return ((MethodCallExpression)expr.Body).Method.GetGenericMethodDefinition();
    }
    private static MethodInfo GetThenByMethod()
    {
        Expression<Func<IOrderedQueryable<object>, IOrderedQueryable<object>>> expr =
            q => q.ThenBy((Expression<Func<object, object>>)null);
        return ((MethodCallExpression)expr.Body).Method.GetGenericMethodDefinition();
    }
    private static MethodInfo GetOrderByDescendingMethod()
    {
        Expression<Func<IQueryable<object>, IOrderedQueryable<object>>> expr =
            q => q.OrderByDescending((Expression<Func<object, object>>)null);
        return ((MethodCallExpression)expr.Body).Method.GetGenericMethodDefinition();
    }
    private static MethodInfo GetThenByDescendingMethod()
    {
        Expression<Func<IOrderedQueryable<object>, IOrderedQueryable<object>>> expr =
            q => q.ThenByDescending((Expression<Func<object, object>>)null);
        return ((MethodCallExpression)expr.Body).Method.GetGenericMethodDefinition();
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With