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

时间:2014-09-14 04:03:09

标签: c# lambda

我不确定提出问题的最佳方式,所以我会尽力解释......

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

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

当输入此方法时,我希望表达式的值以{x =&gt; 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)} 

这完全打破了我想要做的事情。

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

谢谢!

2 个答案:

答案 0 :(得分:0)

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

两个选项:

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

答案 1 :(得分:0)

我相信这应该有效,除非价值可能会在Get之后发生变化。但是,如果你想处理这个问题,你应该自己提取值并使用它。

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

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