我遗漏了一些东西而且我不太清楚什么,我对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](系统)类型的参数.Linq.IQueryable`1 [Shilony.DomainLayer.DomainObjects.Customer],System.String,System.String)'
我没有得到它,当我使用相同的args调用它时它会起作用,但是当我尝试将它全部转换为表达式时它会失败。
答案 0 :(得分:3)
别介意我弄清楚了,我应该仔细研究细节。
在我调用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;
答案 1 :(得分:0)
您无需手动创建表达式树。您可以让编译器以更清晰的方式为您完成。这样可以更容易阅读和维护。
Expression<Func<string, string, IOrderedQueryable<T>>> GetOrderByExpression<T>(IQueryable<T> query)
{
//the compiler will compile the anonymous method into an expression tree
Expression<Func<string, string, IOrderedQueryable<T>>> orderByMethodExpression = (string column, string direction) => query.OrderBy(column, direction);
//return the expression
return orderByMethodExpression;
}