score:7

Accepted answer

This actually turned out to be a GIANT headache to try to solve; but in the end, it actually turned out being very easy to accomplish with a bit of hackishness and reflection:

public class Program
{
    public class SomeClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    static void Main(string[] args)
    {
        List<SomeClass> sample = new List<SomeClass>
        {
            new SomeClass { Id = 4, Name = "ABC" },
            new SomeClass { Id = 1, Name = "XYZ" },
            new SomeClass { Id = 2, Name = "JKL" }
        };

        var result = sample.OrderByDynamic("Name", OrderDirection.Ascending).ToList();

        result.ForEach(x => Console.WriteLine("Id: " + x.Id + " | Name: " + x.Name));

        Console.ReadKey();
    }
}

public enum OrderDirection
{
    Ascending,
    Descending
}

public static class LinqExtensions
{
    public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string propertyName, OrderDirection direction = OrderDirection.Ascending)
    {
        if(direction == OrderDirection.Ascending)
            return source.OrderBy(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
        else
            return source.OrderByDescending(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
    }
}

This example worked for me in test situations; I could supply the property name, and specify a sort direction, and it worked great. Simply call like so:

yourEnumerable.OrderByDynamic("YourPropertyName");
yourEnumerable.OrderByDynamic("YourPropertyName", OrderDirection.Descending);

Enjoy!

score:2

I would change your FunkyOrder method to IEnumerable and implement your dynamic sorting by creating an Expression dynamically like so

public static IEnumerable<T> FunkyOrder<T, TResult>(this IEnumerable<T> input, string fieldname = "Id", string sortdirection = "asc")
{
 ParameterExpresssion parameter = Expression.Parameter(typeof(T), "p");
 Expression property = Expression.PropertyOrField(parameter, fieldname);

 var lambda = Expression.Lambda<Func<T, TResult>>(property, parameter)

 if(sortdirection == "asc")
 {
  return input.OrderBy(lambda.Compile());
 }
 else
 {
  return input.OrderByDescending(lambda.Complile());
 }
}

You will no longer need to cast to ObjectQuery

score:1

You can use Dynamic Linq for dynamic filtering and sorting. This small library (only one single source file) contains extension methods of IQueryable<T> like:

public static IQueryable<T> Where<T>(this IQueryable<T> source,
    string predicate, params object[] values)

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,
    string ordering, params object[] values)

//...and more like GroupBy, Select

Your query on IEnumerable could then be written as:

repository.GetAllProducts().AsQueryable()
    .Where(x => x.Naam.Contains("filter"))
    .OrderBy("FieldName desc")

The library implements all the necessary reflection code to perform those dynamic queries.


Related Articles