我有一个方法可以用来对列表进行排序:
private static IQueryable<T> BuildQuery<T>(IQueryable<T> query,
string methodName,
Expression<Func<T, object>> property)
{
var typeArgs = new[] { query.ElementType, property.Body.Type };
methodCall = Expression.Call(typeof (Queryable),
methodName,
typeArgs,
query.Expression,
property);
return query.Provider.CreateQuery<T>(methodCall);
}
当我使用以下参数执行代码时出现异常:
var myPreExistingQuery = new List<SomeType>{ new SomeType() }.AsQueryable();
var query = BuildQuery(myPreExistingQuery, "OrderBy", x => x.SomeProperty);
异常(exception)情况是:
No method 'OrderBy' on type 'System.Linq.Queryable' is compatible with the supplied arguments.
谁能看到我在这里遗漏了什么?
编辑:
我尝试了 Expression.Call() 的另一个重载并得到了同样的异常:
private static IQueryable<T> BuildQuery<T>(IQueryable<T> query, string methodName, Expression<Func<T, object>> propertyExpression)
{
var methodCall = Expression.Call(query.Expression,
methodName,
new[] {query.ElementType, property.Body.Type},
new[] {propertyExpression});
return query.Provider.CreateQuery<T>(methodCall);
}
最佳答案
由于您希望属性选择器表达式动态地进行适当的调用,因此您必须为其创建一个新表达式。您不能按原样使用提供的选择器,因为它当前输入的是 Expression<Func<T, object>>
并且不返回您的特定类型 Expression<Func<T, SomeType>>
.您可以通过将调用的类型参数更改为接受 object
来使其编译。但它不会按预期工作,因为它将进行对象引用比较(并且您的 LINQ 提供程序可能无论如何都会拒绝它)。
要重新创建您的选择器表达式,您可以这样做:
private static IQueryable<T> BuildQuery<T>(
IQueryable<T> query,
string methodName,
Expression<Func<T, object>> property)
{
var typeArgs = new[] { query.ElementType, property.Body.Type };
var delegateType = typeof(Func<,>).MakeGenericType(typeArgs);
var typedProperty = Expression.Lambda(delegateType, property.Body, property.Parameters);
var methodCall = Expression.Call(
typeof(Queryable),
methodName,
typeArgs,
query.Expression,
typedProperty);
return query.Provider.CreateQuery<T>(methodCall);
}
一个很好的替代方法是使属性类型也通用。这样,您将从一开始就获得适当的强类型选择器。
private static IQueryable<TSource> BuildQuery<TSource, TProperty>(
IQueryable<TSource> query,
string methodName,
Expression<Func<TSource, TProperty>> property)
{
var typeArguments = property.Type.GetGenericArguments();
var methodCall = Expression.Call(
typeof(Queryable),
methodName,
typeArguments,
query.Expression,
property);
return query.Provider.CreateQuery<TSource>(methodCall);
}
关于c# - 在 "supplied arguments"的 Queryable 上找不到 OrderBy。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6892605/