using System.Collections.Generic;
using System.Linq.Expressions;
public static class Program
public static void Main()
var sortOptions = new List<(string propertyName, bool isAscending)>
var items = new List<MyObject> {
new MyObject { Name = "John", Age = 30 },
new MyObject { Name = "John", Age = 31 },
new MyObject { Name = "John", Age = 29 },
new MyObject { Name = "Jane", Age = 25 },
var sortedItems = items.AsQueryable().ApplySorting(sortOptions);
foreach (var item in sortedItems)
Console.WriteLine($"Name: {item.Name}, Age: {item.Age}");
public static IQueryable<T> ApplySorting<T>(this IQueryable<T> source, IEnumerable<(string propertyName, bool isAscending)> sortOptions)
foreach (var (propertyName, isAscending) in sortOptions)
var parameter = Expression.Parameter(typeof(T), "x");
var property = Expression.PropertyOrField(parameter, propertyName);
var lambda = Expression.Lambda(property, parameter);
var methodName = firstSort
? (isAscending ? "OrderBy" : "OrderByDescending")
: (isAscending ? "ThenBy" : "ThenByDescending");
var method = typeof(Queryable).GetMethods()
.First(m => m.Name == methodName && m.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), property.Type);
source = (IOrderedQueryable<T>)method.Invoke(null, new object[] { source, lambda });
public string Name { get; set; }
public int Age { get; set; }