【问题标题】:Use string variable in LINQ lambda expression在 LINQ lambda 表达式中使用字符串变量
【发布时间】:2016-08-05 23:32:11
【问题描述】:

我有一个类属性名称作为字符串变量,并希望在 LINQ 查询中使用它。下面的例子:

public class Demo
{
  public string prop1 {get; set;} 
  public string prop2 {get; set;} 
  public string prop3 {get; set;} 
}

我能做到

var data = db.Single<Demo>(d => d.prop1 == "value");

但不知道运行时的属性是什么并获取字符串参数,例如

string propname = "prop2";

有没有可能在 lambda 表达式 d =&gt; d.propname == "value" 中使用它?我不确定它是否可行,而且在逻辑上似乎也不可能。所以想发布一个问题,看看是否有办法。请提出建议。

请注意,Single() 调用发生在MongoDB C# Driver 上,因此不确定反射是否会起作用。

【问题讨论】:

  • 可能是 Linq Expression 的工作(不要与 lambda 表达式混淆);在给定参数的情况下即时编译正确的“事物”。
  • 对于两个回答所有者,错过指出它在 MongoDB C# 驱动程序上。对此很抱歉,但不管怎样,这两个答案都是好的和有效的。
  • @Rahul 你试过了吗?
  • @Ignaus,我在路上,所以不能确定。
  • @Sehnsucht,感谢您指出这一点,但不幸的是,这是我不懂的非英语。但是你在说什么。

标签: c# mongodb linq mongodb-.net-driver


【解决方案1】:

(这是在意识到反射在这种特殊情况下无济于事之前提供的原件。请参阅下面的编辑以获取更新的答案)

如果你不介意使用反射,你可以这样做:

var data = db.Single<Demo>(d => "value" == (string)typeof(Demo).GetProperty(propname).GetValue(d));

编辑

正如其他人在 cmets 中所暗示的那样,要使其与 MongoDB 一起使用,您必须“手动”构建表达式。

所以,如果我采取以下陈述:

var data = db.Single<Demo>(d => d.prop1 == "value");

我认为以下应该是等价的,但要手动构建 lambda 表达式:

string propname = "prop1"; // you can now change this to any valid property name.

var parameterExpresion = Expression.Parameter(typeof(Demo), "d");
var binaryExpression = Expression.Equal(
    Expression.Property(parameterExpresion, propname),
    Expression.Constant("value"));
var lambda = Expression.Lambda<Func<Demo, bool>>(binaryExpression, parameterExpresion);

var data = db.Single<Demo>(lambda);

...除了现在,您应该能够将propname 的值更改为任何有效的属性名称,并且应该可以正常工作。

查看手动构建 lambda 时代码变得多么冗长确实有助于我了解在我们没有注意到的情况下发生的所有编译器魔法。

【讨论】:

  • 感谢 sstan,虽然不确定反射是否会起作用,因为 Single 电话正在 MongoDB C# Driver 上进行,但值得一试。
  • 不确定,除非尝试过,否则不能说,但答案仍然不错。
  • @Rahul 你应该在你的问题中添加带有适当标签的 MongoDB 部分
  • 我编辑了我的答案以提供一个适用于 MongoDB 的解决方案。
  • 这个答案值得更多投票,是的,这就是前进的道路。因为怀疑的反思没有帮助。感谢您为提出答案所做的努力。我还建议不要删除您的第一个答案,也将其包括在内并将这个修改后的答案附加为 EDIT。 Cool mate ...有一天会在您的问题上回复您的帮助。
【解决方案2】:

编辑:此答案不适用于 MongoDB。请参阅@sstan 的回答。

正如@sstan 所说,您可以使用反射:

var property = typeof(Demo).GetProperty("propertyName");
var data = db.Single<Demo>(d => (string)property.GetValue(d) == "value");

propertyPropertyInfo 类型的对象,它有一个方法 GetValue。此方法接受一个对象并返回该对象的指定属性。

另外,在@sstan 的示例中,typeof(Demo).GetProperty("propertyName") 将为每个可能是数百万的对象(取决于您的数据库的大小)调用。最好事先得到一次,然后重复使用。

【讨论】:

  • 你测试过吗,如果没有表达式树,这将如何工作?
  • @johnny5 不,我没有,我在 MongoDB 问题出现之前发布了答案。
  • 这不应该在实体框架上工作,或者 db 暗示它是一个 orm。如果您将其转换为表达式,您的答案可能会起作用。请进行编辑
  • @johnny5 sstan 已经给出了很好的答案,我的现在应该被忽略
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多