将一段代码转换为表达式

本文关键字:代码 转换 表达式 一段 | 更新日期: 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;
}