将一段代码转换为表达式
本文关键字:代码 转换 表达式 一段 | 更新日期: 2023-09-27 18:08:17
我错过了一些东西,我不太确定是什么,我没有很多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 '上没有泛型方法'OrderBy'。QueryableExtensions'与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。
为了澄清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. linq类型的表达式。IQueryable'不能用于'System.Linq.IQueryable 1[Shilony.DomainLayer.DomainObjects.Customer]' of method 'System.Linq.IQueryable
[Shilony.DomainLayer.DomainObjects. properties]类型的参数。客户]OrderBy[客户]([Shilony.DomainLayer.DomainObjects System.Linq.IQueryable ' 1。客户)系统。system . String)字符串,'
我不明白,当我用相同的参数调用它时,它可以工作,但当我试图将其全部转换为表达式时,它失败了
没关系,我已经弄明白了,我应该更仔细地研究一下细节。
在调用表达式之前。调用表达式树如下所示。
{System.Linq.IQueryable ' 1 [Shilony.DomainLayer.DomainObjects。客户]OrderBy[客户](来。这个IQueryable、系统。system . String )}
在我调用了表达式之后。调用表达式变成如下。
{System.Collections.Generic.List ' 1 [Shilony.DomainLayer.DomainObjects.Customer]。OrderBy("姓",null)}
问题和我的错误是,我试图传递CreateQuery的表达式,这是由调用的结果。
返回的类型是一个列表,因为OrderBy是IQueryable方法的扩展,所以它试图再次调用它,失败的问题是因为现在应该用不同数量的参数调用OrderBy System.Linq。IQueryable应该被排除,因此它会抛出以下异常:
在类型'Shilony.Web.UI.WebControls '上没有泛型方法'OrderBy'。QueryableExtensions'与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。
解决方案如下
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;
您不需要手动创建表达式树。你可以让编译器以一种更清晰的方式为你做这件事。这将使它更容易阅读和维护。
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;
}