C# 表达式。或者,参数';项目';不在范围之内

C# 表达式。或者,参数';项目';不在范围之内,c#,linq,expression-trees,expression,C#,Linq,Expression Trees,Expression,我试图为一两个表达式编写一个静态函数,但收到以下错误: 参数“item”不在范围内 描述:未处理的异常 在执行过程中发生 当前web请求。请检查 有关堆栈跟踪的详细信息,请参阅 错误及其来源 密码 例外情况详情: System.InvalidOperationException:异常 参数“item”不在范围内 方法: public static Expression<Func<T, bool>> OrExpressions(Expression<Func<T

我试图为一两个表达式编写一个静态函数,但收到以下错误:

参数“item”不在范围内

描述:未处理的异常 在执行过程中发生 当前web请求。请检查 有关堆栈跟踪的详细信息,请参阅 错误及其来源 密码

例外情况详情: System.InvalidOperationException:异常 参数“item”不在范围内

方法:

public static Expression<Func<T, bool>> OrExpressions(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
    // Define the parameter to use
    var param = Expression.Parameter(typeof(T), "item");

    var filterExpression = Expression.Lambda<Func<T, bool>>
         (Expression.Or(
             left.Body,
             right.Body
          ), param);
    // Build the expression and return it
    return (filterExpression);
}
公共静态表达式或表达式(表达式左、表达式右)
{
//定义要使用的参数
var param=表达式参数(类型(T),“项”);
var filtereexpression=Expression.Lambda
(表示)或(
左,身体,
对,尸体
),param);
//构建表达式并返回它
返回(filterExpression);
}
编辑:添加更多信息

正在或的表达式来自下面的方法,执行得很好。如果有更好的方法或结果,我洗耳恭听。另外,我不知道有多少人是被提前录取的

public static Expression<Func<T, bool>> FilterExpression(string filterBy, object Value, FilterBinaryExpression binaryExpression)
{
    // Define the parameter to use
    var param = Expression.Parameter(typeof(T), "item");

    // Filter expression on the value
    switch (binaryExpression)
    {
        case FilterBinaryExpression.Equal:
            {
                // Build an expression for "Is the parameter equal to the value" by employing reflection
                var filterExpression = Expression.Lambda<Func<T, bool>>
                    (Expression.Equal(
                        Expression.Convert(Expression.Property(param, filterBy), typeof(TVal)),
                        Expression.Constant(Value)
                     ),
                    param);
                // Build the expression and return it
                return (filterExpression);
            }
公共静态表达式FilterExpression(字符串filterBy、对象值、FilterBinaryExpression binaryExpression)
{
//定义要使用的参数
var param=表达式参数(类型(T),“项”);
//筛选值上的表达式
开关(二进制表达式)
{
大小写筛选器二进制表达式。相等:
{
//通过使用反射为“参数是否等于值”构建表达式
var filtereexpression=Expression.Lambda
(表示)相等(
Expression.Convert(Expression.Property(param,filterBy),typeof(TVal)),
表达式.常量(值)
),
参数);
//构建表达式并返回它
返回(filterExpression);
}
编辑:添加更多信息

或者,有没有更好的方法来执行or?目前.Where(constraint)在constraint类型为Expression>的情况下运行良好。如何执行Where(constraint t1或constraint t2)(到约束n'th)


提前感谢!

问题在于您在方法或表达式中创建的表达式重用了两个表达式的主体。这些主体将包含对FilterExpression中定义的自己的ParameterExpression的引用


解决方法是重写左右部分以使用新的ParameterExpression。或者传递原始的ParameterExpression。这并不是因为两个ParameterExpression具有相同的名称,而是因为它们代表相同的参数。

我不确定这里的正确术语,但基本上表达式参数并不等价即使他们有相同的名字

也就是说

var param1 = Expression.Parameter(typeof(T), "item");
var param2 = Expression.Parameter(typeof(T), "item");

param1 != param2
如果在表达式中使用,param1和param2将不相同

处理此问题的最佳方法是为表达式预先创建一个参数,然后将其传递给所有需要该参数的帮助器函数

编辑:另外,如果您试图在LINQ中动态组合where子句,您可以试一试。

如前所述,您可以找到这段非常好的(有效的)代码

公共静态表达式或(此表达式expr1,表达式expr2)
{
var invokedExpr=Expression.Invoke(expr2,expr1.Parameters.Cast());
返回Expression.Lambda(Expression.Or(expr1.Body,invokedExpr),expr1.Parameters);
}

我也想到了Fabrizio的解决方案,但由于我试图将两个表达式组合起来作为LINQ 2 sql查询执行,所以我认为它将在内存中执行,而不是在sql server中执行


我被写到-Linq To Sql认识到调用是lambda表达式,因此仍然会生成优化的Sql。

对于那些通过搜索引擎找到此页面并打算使用Ben&Joe Albahari的PredicateBuilder的人,请小心,因为它不适用于实体框架


试试吧。

谢谢!现在就要尝试传递相同的参数了。我的朋友,你真是太棒了:)谢谢:)我重新修改了方法,将相同的参数传递给助手的方法,一切又好了。我正在研究PredicateBuilder,希望它能帮你解决问题,因为Ben&Joe Albahari的PredicateBuilder就是这样做的不适用于实体框架。有关固定版本,请参阅我的答案。请注意,因为此代码不适用于实体框架。有关固定版本,请参阅我的答案。
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
    var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
    return Expression.Lambda<Func<T, bool>>(Expression.Or(expr1.Body, invokedExpr), expr1.Parameters);
}