我遗漏了一些东西,我不太确定是什么,我对 LINQ 表达式没有很多经验。
我正在尝试将以下代码更改为表达式。
MethodInfo orderByMethod = (from method in typeof(QueryableExtensions).GetMethods()
where method.Name == "OrderBy" && method.GetGenericArguments().Length > 0
select method).First();
MethodInfo orderByGenericMethod = orderByMethod.MakeGenericMethod(new[] { queryable.ElementType });
IQueryable queryable = orderByGenericMethod.Invoke(null, new object[] { queryable, sorting.ColumnName, sorting.Direction }) as IQueryable;
这是我的尝试。
Expression orderByMethodExpression = Expression.Call(typeof(QueryableExtensions), "OrderBy", new[] { queryable.ElementType },
Expression.Constant(queryable),
Expression.Constant(sorting.ColumnName),
Expression.Constant(sorting.Direction));
IQueryable queryable = queryable.Provider.CreateQuery(orderByMethodExpression)
相关代码。
SortingExpression sorting = SortingExpression.Create(arguments.SortExpression);
IQueryable queryable = enumerable.AsQueryable();
if (sorting != null)
{
MethodInfo orderByMethod = (from method in typeof(QueryableExtensions).GetMethods()
where method.Name == "OrderBy" && method.GetGenericArguments().Length > 0
select method).First();
MethodInfo orderByGenericMethod = orderByMethod.MakeGenericMethod(new[] { queryable.ElementType });
queryable = orderByGenericMethod.Invoke(null, new object[] { queryable, sorting.ColumnName, sorting.Direction }) as IQueryable;
}
object[] items = Enumerable.Cast<object>(queryable).ToArray();
arguments.TotalRowCount = items.Length;
enumerable = items;
我得到的错误。
类型 'Shilony.Web.UI.WebControls.QueryableExtensions' 上的通用方法 'OrderBy' 与提供的类型参数和参数不兼容。如果方法是非通用的,则不应提供类型参数。
只是为了澄清 OrderBy 是我自己的扩展方法,这里是方法的签名。
public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName, string direction) where TSource : class
只是为了了解出了什么问题,我将其更改为这个。
MethodInfo orderByMethod = (from method in typeof(QueryableExtensions).GetMethods()
where method.Name == "OrderBy" && method.GetGenericArguments().Length > 0
select method).First();
MethodInfo orderByGenericMethod = orderByMethod.MakeGenericMethod(new[] { queryable.ElementType });
Expression orderByMethodExpression = Expression.Call(orderByGenericMethod,
Expression.Constant(queryable, typeof(IQueryable)),
Expression.Constant(sorting.ColumnName, typeof(string)),
Expression.Constant(sorting.Direction, typeof(string)));
queryable = queryable.Provider.CreateQuery(orderByMethodExpression);
现在我收到这个错误。
“System.Linq.IQueryable”类型的表达式不能用于“System.Linq.IQueryable”类型的参数
1[Shilony.DomainLayer.DomainObjects.Customer]' of method 'System.Linq.IQueryable
1[Shilony.DomainLayer.DomainObjects.Customer] OrderBy[Customer](System.Linq.IQueryable`1[Shilony.DomainLayer] .DomainObjects.Customer], System.String, System.String)'我不明白,当我使用相同的参数调用它时,它可以工作,但是当我尝试将其全部转换为表达式时,它会失败。
最佳答案
没关系,我想通了,我应该更仔细地查看细节。
在我调用 Expression.Call 之前,表达式树看起来像这样。
{System.Linq.IQueryable`1[Shilony.DomainLayer.DomainObjects.Customer] OrderBy[Customer]( System.Linq.IQueryable, System.String, System.String )}
在我调用 Expression.Call 之后,表达式变成了以下内容。
{System.Collections.Generic.List`1[Shilony.DomainLayer.DomainObjects.Customer].OrderBy("LastName", null)}
问题和我的错误是我试图将调用产生的表达式传递给 CreateQuery。
返回的类型是一个列表,因为 OrderBy 是 IQueryable 的扩展方法,该方法存在于那里,所以它尝试再次调用它,失败的问题是因为现在应该使用不同数量的参数调用 OrderBy System.Linq.IQueryable 应该被排除在外,因此它会引发以下异常。
类型 'Shilony.Web.UI.WebControls.QueryableExtensions' 上的通用方法 'OrderBy' 与提供的类型参数和参数不兼容。如果方法是非通用的,则不应提供类型参数。
这是解决方案。
Expression orderByExtensionMethodExpression = Expression.Call(typeof(QueryableExtensions), "OrderBy", new[] { queryable.ElementType },
Expression.Constant(queryable),
Expression.Constant(sorting.ColumnName),
Expression.Constant(sorting.Direction, typeof(string)));
queryable = Expression.Lambda(orderByExtensionMethodExpression).Compile().DynamicInvoke() as IQueryable;