extmethod

If not or you are struggling to understand it, then no worries.  I too didn’t understand it fully well when I coded this, but it worked wonderfully.  I am going to break down this code into digestible parts because there is just too much.  I would suggest going through the provided links as well to fully understand each part before going to the next.

In the code, I am declaring a new extension method, named OrderByWithDirection, to be used as a LINQ query operation to sort elements in either ascending or descending order.  See Standard Query Operators Overview.  In LINQ query, you have separate methods for sorting in ascending order, the OrderBy , and sorting in descending order, the OrderByDescending.  OrderByWithDirection can do both ways, so I am passing a sort direction in the third parameter:

public static IOrderedQueryable<TSource> OrderByWithDirection<TSource, TKey>( this IQueryable<TSource> query, Expression<Func<TSource, TKey>> keySelector, string sortDir) 

So what’s an extension method?  An extension method is like a static function that you can add to an existing type so you can call it from any instance of that (extended) type.  See Extension Methods and How to: Implement and Call a Custom Extension Method.  In the code, I am making OrderByWithDirection available to any data structures that implement _IQueryable_, which is why the first parameter to this method is of that type:

public static IOrderedQueryable<TSource> OrderByWithDirection<TSource, TKey>( this IQueryable<TSource> query, Expression<Func<TSource, TKey>> keySelector, string sortDir) 

Depending on the sort direction, OrderByWithDirection calls either OrderBy or OrderByDescending, both of which are actually extension methods themselves extending IQueryable<TSource>.  So it’s only logical that OrderByWithDirection extends the same type as well.  OrderBy and OrderByDescending are part of the Queryable class, much like OrderByWithDirection is part of ExtensionMethods class in the code.  See Queryable Class, Queryable.OrderBy Method, and Queryable.OrderByDescending Method.

OrderBy and OrderByDescending requires an Expression<Func<TSource, TKey>>, basically a function to extract a key from an element.  So in OrderByWithDirection, I am passing this function on the second parameter:

public static IOrderedQueryable<TSource> OrderByWithDirection<TSource, TKey>( this IQueryable<TSource> query, Expression<Func<TSource, TKey>> keySelector, string sortDir) 

To call OrderByWithDirection you would code something like this:

// products variable is of type IQueryable<Product> 
products = products.OrderByWithDirection(p => p.ProductName, "desc"); 

Here we are passing a lambda expression.  At first, it might look like this lambda expression is returning the product name value and not the product name key, ProductName.  But because we are passing this as an Expression<Func<TSource, TKey>>, the lambda expression is being represented as an expression tree which makes this possible.  See Expression<TDelegate> Class, Func<T, TResult> Delegate, Expression Trees, and How to: Use Expression Trees to Build Dynamic Queries.

Last but not the least, the return type.  Since OrderByWithDirection returns whatever the OrderBy or OrderByDescending returns, it’s only logical to return the same type as well, which is IOrderedQueryable<TSource>. See IOrderedQueryable Interface.

Below is the complete code in text:

using System;
using System.Linq;
using System.Linq.Expressions;

public static class ExtensionMethods {
  public static IOrderedQueryable < TSource > OrderByWithDirection < TSource, TKey > (this IQueryable < TSource > query, Expression < Func < TSource, TKey >> keySelector, string sortDir) {
    if (sortDir.ToUpper().Equals("DESC")) {
      return query.OrderByDescending(keySelector);
    } else {
      return query.OrderBy(keySelector);
    }
  }
}