0

I have written the LINQ query as following but just wondering if i can make it more generic and get rid of the hard coded values.

switch (sortOrder)
{
    case "DESC":
        if(sortBy == "A")
            query = query.OrderByDescending(x => x.Field1);
        if(sortBy == "B")
            query = query.OrderByDescending(x => x.Field2);
        if (sortBy == "C")
            query = query.OrderByDescending(x => x.Field3);
        break;
    default:
        if(sortBy == "A")
            query = query.OrderBy(x => x.Field1);
        if(sortBy == "B")
            query = query.OrderBy(x => x.Field2);
        if (sortBy == "C")
            query = query.OrderBy(x => x.Field3);
        break;
}

The link mentioned as duplicate is not the answer i am looking for. In that question user asked by sorting 1st of ASC and then Desc.

In my case i have to either sort ASC or DESC.

simbada
  • 772
  • 1
  • 18
  • 38

2 Answers2

2

You can only do that using Reflection i guess:

static IEnumerable<T> Order<T, V>(IEnumerable<T> query, string sortOrder, 
                                    Func<T, V> fieldSelector)
{
    string methodName = sortOrder == "DESC" ? "OrderByDescending" : "OrderBy";
    MethodInfo method = typeof(Enumerable).GetMethods()
                                          .Where(x => x.Name.Contains(methodName))
                                          .FirstOrDefault();

    MethodInfo genericMethod = method.MakeGenericMethod(typeof(Resource), typeof(V));

    var orderedResults = (IEnumerable<T>)genericMethod.Invoke(null, 
                                    new object[] { query, fieldSelector });

    return orderedResults;
}

Usage:

var orderdResults = Order(query, "DESC", x => x.CategoryId).ToList();
Zein Makki
  • 27,184
  • 5
  • 44
  • 56
  • Please fix your formatting such that we can read it without scrolling vertically. Also this wont work for `IQueryable`s, i.e. it won't work with Entity Framework. `fieldSelector` should be an `Expression>`. – Good Night Nerd Pride Jul 04 '16 at 08:08
0

I don't get why you would want to reimplement LINQ's OrderBy(), but this is the most sensible way to do it, I guess:

public static class Extensions
{
    public static IOrderedQueryable<TSource> Order<TSource, TKey>(
        this IQueryable<TSource> source, 
        Expression<Func<TSource, TKey>> keySelector, 
        bool descending = false)
    {
        return descending 
            ? source.OrderByDescending(keySelector)
            : source.OrderBy(keySelector);
    }   
}

You'd use it like the standard OrderBy(), i.e. you give it an expression that selects a property of TSource:

var newest = query.Order(x => x.Id, true).First();
var oldest = query.Order(x => x.Id).First();

Workinge example: https://dotnetfiddle.net/TcEEqY

Good Night Nerd Pride
  • 6,287
  • 3
  • 38
  • 54