我有一个方法需要IQueryable<T>
,我想在其中一般实现OrderBy。理想情况下,通过传入c => c.SomeProperty
作为参数,但我无法弄清楚如何让泛型工作,所以我用字符串尝试了它。但是我收到了错误:
Incorrect number of parameters supplied for lambda declaration
这是我尝试的(使用字符串方法)
var sortSelectorParameter = Expression.Parameter(typeof(T), "c");
var sortSelector = Expression.PropertyOrField(sortSelectorParameter, "ClientId"); // ClientId is the property string
collection = collection.OrderByDescending(Expression.Lambda<Func<T, bool>>(sortSelector));
我很困惑,因为OrderBy只接受一个参数 - 任何建议?
答案 0 :(得分:3)
您需要将参数传递给Expression::Lambda<T>
,如错误所示:
var sortSelectorParameter = Expression.Parameter(typeof(T), "c");
var sortSelector = Expression.PropertyOrField(sortSelectorParameter, "ClientId"); // ClientId is the property string
collection = collection.OrderByDescending(Expression.Lambda<Func<T, bool>>(sortSelector, sortSelectorParameter ));
你&#34;身体&#34;对于lambda,引用参数c
,由ExpressionParameter
实例sortSelectorParameter
表示。您需要将此参数实例传递给lambda,以便它知道body引用的参数实际上是您要创建的lambda的in-parameter。
编辑:以上内容可能会回答您的技术问题,但目前尚不清楚您要在此处实现的目标。如果你只是想在编译时通过你知道的东西订购,那么你就不需要这些了。包装OrderByDescending
- 方法有什么意义?
IQueryable<TElement> MySpecialOrderBy<TElement, TKey>(IQueryable<TElement> source, Expression<Func<TElement, TKey>> keySelector)
{
return source.OrderByDescending(keySelector);
}
答案 1 :(得分:1)
这很复杂:
private static readonly MethodInfo OrderByDescending = (from x in typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public)
where x.Name == "OrderByDescending"
let args = x.GetGenericArguments()
where args.Length == 2
let pars = x.GetParameters()
where pars.Length == 2 &&
pars[0].ParameterType == typeof(IQueryable<>).MakeGenericType(args[0]) &&
pars[1].ParameterType == typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(args))
select x).Single();
public static IQueryable<T> OrderByStringDescending<T>(this IQueryable<T> query, string parameter)
{
var par = Expression.Parameter(typeof(T), "obj");
var selector = Expression.PropertyOrField(par, parameter);
var lambda = Expression.Lambda(selector, par);
return (IQueryable<T>)OrderByDescending.MakeGenericMethod(typeof(T), selector.Type).Invoke(null, new object[] { query, lambda });
}
您必须构建Expression.Lambda
。问题是在编译时不知道Queryable.OrderByDescending
类型而调用IQueryable<>
(具有两个参数,Expression<>
查询和TKey
)时间很复杂。我通过反思来解决它。
答案 2 :(得分:1)
如果您只需要传递一个表达式,那么使用该集合执行其他操作的方法就很简单了:
public void Test<T,TKey>(IQueryable<T> collection, Expression<Func<T,TKey>> orderByExpr)
{
// your logic here
// ...
collection = collection.OrderByDescending(orderByExpr);
}
你这样称呼它:
this.Test(collection, c => c.ClientId);