【问题标题】:how to use multiple parameters when combining expressions using Expression.Lambda使用 Expression.Lambda 组合表达式时如何使用多个参数
【发布时间】:2016-08-12 10:40:40
【问题描述】:

好的,这就是我正在动态创建一个表达式以针对数据库执行的问题,它工作正常。当我使用 Expression.AndAlso 添加另一个表达式时出现问题,表达式组合得很好,但参数不起作用,我的代码如下。

Expression<Func<Invoice, bool>> condition = null;

ParameterExpression[] param = new ParameterExpression[sessionModel.FilterChildren.Count];

foreach (var filter in sessionModel.FilterChildren) {

   param[i] = Expression.Parameter(typeof(Invoice), filter.SysName);

   Type type = Type.GetType(filter.Type);

   if (i == 0)
     condition =
         Expression.Lambda<Func<Invoice, bool>>(
             Expression.Equal(
             Expression.Property(param[i], filter.SysName),
             Expression.Constant(filter.Value, type)
            ),
              param[i]);
    else {
      var newCond = Expression.Lambda<Func<Invoice, bool>>(
         Expression.Equal(
             Expression.Property(param[i], filter.SysName),
             Expression.Constant(filter.Value, type)
            ),
              param[i]);

       var test = Expression.AndAlso(condition.Body, newCond.Body);

       condition = Expression.Lambda<Func<Invoice, bool>>(test, param);
    }
    i++;
  }

会报错

Incorrect number of parameters supplied for lambda declaration

每个要添加的表达式都有不同的参数。

任何想法我哪里出错了?

谢谢

【问题讨论】:

  • 您是否在if 块之前为condition 赋值?
  • 我已经更新了我的问题以显示之前的名称:)
  • 好吧,我希望 NullReferenceException 像你一样 Expression&lt;Func&lt;Invoice, bool&gt;&gt; condition = null; 然后如果没有触发块 var test = Expression.AndAlso(condition.Body, newCond.Body); 但我猜 i 最初也是 0,所以情况并非如此.哪一行抛出异常? AndAlso 部分对我没有经验的眼睛来说似乎没问题。
  • 很快 - 你应该使用一个相同的参数。
  • 问题出在 line condition = Expression.Lambda>(test, param);并且似乎也可以正常工作

标签: c# entity-framework lambda expression


【解决方案1】:

使用 Expression.Lambda 组合表达式时如何使用多个参数

您不应该使用多个参数。 lambda 表达式

Expression<Func<Invoice, bool>> condition

暗示Invoice类型的单个参数。

要解决问题,请替换

ParameterExpression[] param = new ParameterExpression[sessionModel.FilterChildren.Count];

var param = Expression.Parameter(typeof(Invoice), "invoice");

在其余代码中,将param[i] 替换为param

附:没有真正需要为每个过滤器创建 lambda 表达式,因为如您所见,在组合它们时,您只使用 Body。整个过程可以精简成这样:

Expression<Func<Invoice, bool>> condition = null;
if (sessionModel.FilterChildren.Any())
{
    var parameter = Expression.Parameter(typeof(Invoice), "invoice");
    var body = sessionModel.FilterChildren
        .Select(filter => Expression.Equal(
            Expression.Property(parameter, filter.SysName),
            Expression.Constant(filter.Value, Type.GetType(filter.Type))))
        .Aggregate(Expression.AndAlso);
    condition = Expression.Lambda<Func<Invoice, bool>>(body, parameter);
}

【讨论】:

  • 只是想学习,所以听起来可能很愚蠢,但这背后的原因是什么? param[i] 不也是 ParameterExpressionExpression.Lambda 中所期望的吗?
  • 是的。但它们是不同的对象,不被认为是一回事。连名字都无所谓。所以真正的技巧是使用一个相同的参数表达式instance
  • 有道理 :) 谢谢你...传奇
  • 刚刚添加了一种简化的方法(用于学习目的:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多