使用现有的 Queryable 方法转换 C# 表达式

问题描述 投票:0回答:1

我需要将方法附加到现有表达式并将它们组合成一个新的 resultExpression。

Expression<TSource, IQueryable<TResult>> sourceExpression;
Expression<TSource, int, int, IQueryable<TResult>> resultExpression;

我需要将 Queryable.Skip() 和 Queryable.Take() 方法附加到 sourceExpression 并完全转换为 resultExpression。 我如何使用 C# 表达式方法来做到这一点?

我尝试将 Expression.Lambda> 与 Expression.Call 一起使用,但当我将 Queryable 方法传递给 Expression.Call 参数时,它会抛出 InvalidOperationException

var skipCall = Expression.Call(
                typeof(Queryable),
                nameof(Queryable.Skip),
                new[] {typeof(TResult)},
                sourceExpression.Body,
                Expression.Parameter(typeof(int))
            );
 var takeCall = Expression.Call(
                typeof(Queryable),
                nameof(Queryable.Take),
                new[] {typeof(TResult)},
                skipCall,
                Expression.Parameter(typeof(int))
            );
 var resultExpression = Expression.Lambda<Func<TSource, int, int, IQueryable<TResult>>>(
                takeCall, sourceExpression.Parameters
            );

“System.Linq.Queryable”类型上的泛型方法“Take”与提供的类型参数和参数不兼容。如果方法是非泛型的,则不应提供类型参数

c# lambda iqueryable linq-expressions
1个回答
0
投票

Skip
是通用的,至少接受2个参数,传入
IQueryable<T>
int
,所以需要创建一个封闭的方法:

var method = typeof(Queryable).GetMethod(nameof(Queryable.Skip), new Type[]
    {
        typeof(IQueryable<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
        typeof(int)
    })
    .MakeGenericMethod(typeof(TResult));

然后用它来构建表达式。

© www.soinside.com 2019 - 2024. All rights reserved.