将变量传递到表达式谓词并获得意外结果

本文关键字:意外 结果 谓词 表达式 变量 | 更新日期: 2023-09-27 18:21:44

我不确定问这个问题的最佳方式,所以我会尽力解释。。。

我有一个我调用的方法,显示在这里:

public List<T> Get<T>(Expression<Func<T, bool>> expression)
{ ... }

当输入此方法时,我希望表达式的值为{x=>x.RecordNumber==123456}

当我这样称呼它时,它会像预期的那样工作:

var customers = MyClass.Get<Customer>(x => x.RecordNumber == 123456);

然而,当我在尝试将123456作为变量传递时调用它时,(对我来说)发生了一些意想不到的事情。。。所以说我愿意:

long recordNumber = 123456;
var customers = _unitOfWork.Get<Customer>(x => x.RecordNumber == recordNumber);

然后我得到了一些类似的东西

{x => (x.RecordNumber == value(MyCallingClass+>c__DisplayClass2).recordNumber)} 

这完全破坏了我的努力。

如何通过传递变量而不是硬编码值来获得预期结果?有人见过这个,知道我做错了什么吗?

谢谢!

将变量传递到表达式谓词并获得意外结果

如果Lambda中使用了变量,则Lambda语法会自动设置闭包。您的Get<T>实现似乎期望一个表达式树与一个数字常量进行比较,但您希望能够在创建表达式时更改该数字。

两种选择:

  1. 在不使用lambda语法的情况下,自己构建Expression<Converter<T, bool>>,并为数字文本添加一个表达式节点,传递所需的变量值
  2. 重写Get<T>,以便能够处理包含变量引用的表达式,并从变量中获取数值

我认为这应该有效,除非Get之后值可能会发生变化。然而,如果你想处理这个问题,你可能应该自己提取值并使用它。

var thisIsYourValueExtractedImmediately = 
    Expression.Lambda((expression.Body as BinaryExpression).Right)
        .Compile().DynamicInvoke();

这显然需要类型检查,但是它会立即取出您的常量,以便您可以存储它并使用该值。