我遗漏了一些东西,我不太确定是什么,我对 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;

10-06 13:08
查看更多