在 LINQ lambda 表达式中使用字符串变量

Use string variable in LINQ lambda expression

我有一个 class 属性 名称作为字符串变量,想在 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 => d.propname == "value"?我不确定它是否可以并且在逻辑上似乎是不可能的。所以想到发布一个问题,看看是否有办法。请推荐。

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

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

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

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

编辑

正如其他人在评论中暗示的那样,要使此功能与 MongoDB 一起使用,您必须构建表达式 "by hand".

所以,如果我采用以下语句:

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 时代码变得多么冗长确实帮助我欣赏在我们没有注意到的情况下发生的所有编译器魔法。

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

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

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

property 是一个 PropertyInfo 类型的对象,它有一个方法 GetValue。此方法采用一个对象和 returns 该对象的指定 属性.

此外,在@sstan 的示例中,将为每个对象调用 typeof(Demo).GetProperty("propertyName"),每个对象(取决于您的数据库的大小)可能是数百万。最好提前拿到一次再利用。