/// <summary>
/// Sorts the elements of a sequence in ascending or decsending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similiar to the way String.Format formats strings.</param>
/// <returns>A <see cref="IQueryable"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
/// <example>
/// <code>
/// var result = list.OrderBy("NumberProperty, StringProperty DESC");
/// </code>
/// </example>
public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] args)
{
Validate.Argument(source, "source").IsNotNull().Check()
.Argument(ordering, "ordering").IsNotNull().IsNotEmpty().IsNotWhiteSpace().Check();
ParameterExpression[] parameters = new ParameterExpression[] {
Expression.Parameter(source.ElementType, "")
};
ExpressionParser parser = new ExpressionParser(parameters, ordering, args);
IEnumerable <DynamicOrdering> orderings = parser.ParseOrdering();
Expression queryExpr = source.Expression;
string methodAsc = "OrderBy";
string methodDesc = "OrderByDescending";
foreach (DynamicOrdering o in orderings)
{
queryExpr = Expression.Call(
typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
new Type[] { source.ElementType, o.Selector.Type },
queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));
methodAsc = "ThenBy";
methodDesc = "ThenByDescending";
}
return(source.Provider.CreateQuery(queryExpr));
}