Есть две "проблемы" с методом OrderBy
: он имеет перегрузки и является общим. Сначала вам нужно выбрать правильную перегрузку:
var openOrderBy = typeof(Queryable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.First(m => m.Name == "OrderBy" && m.GetParameters().Length == 2);
(примечание: здесь я использую простую проверку на основе количества параметров, вы можете прочитать больше здесь )
Тогда вам нужно привязать его к конкретным типам:
var closedOrderBy = openOrderBy.MakeGenericMethod(
typeof(string), // type of item in collection, TSource
typeof(string)); // type returned by lambda, TKey
Теперь вы можете использовать это MethodInfo
в Expression.Call
:
var pe = Expression.Parameter(typeof(string), "company");
var orderByCall = Expression.Call(null, // for static methods
closedOrderBy,
companies.AsQueryable().Expression,
Expression.Lambda<Func<string, string>>(pe, pe));
Вы можете проверить это с помощью дополнительной лямбды:
var result = Expression.Lambda<Func<IQueryable<string>>>(orderByCall)
.Compile().Invoke().ToList();
result.ForEach(Console.WriteLine);
Демо
<ч />
Обновление: , как сказал @Ivan Stoev в комментарии, ответ может быть упрощен
var queryableData = companies.AsQueryable();
var pe = Expression.Parameter(typeof(string), "company");
var orderByCall = Expression.Call(typeof(Queryable),
"OrderBy",
new []{ queryableData.ElementType,
queryableData.ElementType }, // <-- fix #1 select correct overload
queryableData.Expression, // <-- fix #2 pass first argument
Expression.Lambda<Func<string, string>>(pe, pe)
);