【问题标题】:Dynamic lambda expression for array property filter数组属性过滤器的动态 lambda 表达式
【发布时间】:2015-12-06 13:35:57
【问题描述】:

根据要求,我想使用 C# 创建一个动态 lambda 表达式。

例如我想生成像

这样的动态查询
Employee. Address[1].City

我该怎么做?请注意,该属性是动态属性。

我试过这段代码

var item = Expression.Parameter(typeof(Employee), "item");

Expression prop = Expression.Property(item, "Address", new Expression[] { Expression.Constant[1] });
prop = Expression.Property(prop, "City");

var propValue = Expression.Constant(constraintItem.State);
var expression = Expression.Equal(prop, propValue);
var lambda = Expression.Lambda<Func<Line, bool>>(expression, item);

但它不起作用。

任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • Address 是索引器吗?如果是数组,则使用Expression.ArrayIndex,如果只是带有索引器的列表,则使用未索引的Expression.Property 检索列表,然后在其Items 属性上应用索引属性检索表达式。

标签: c# linq lambda


【解决方案1】:

你的“动态查询”表达式(这不是真正的查询,它是一个简单的MemberExpression)可以产生如下:

ParameterExpression param = Expression.Parameter(typeof(Employee), "item");
MemberExpression address = Expression.Property(param, "Address");
BinaryExpression indexedAddress = Expression.ArrayIndex(address, Expression.Constant(1));
MemberExpression city = Expression.Property(indexedAddress, "City"); // Assuming "City" is a string.

// This will give us: item => item.Address[1].City
Expression<Func<Employee, string>> memberAccessLambda = Expression.Lambda<Func<Employee, string>>(city, param);

如果您希望将实际的 谓词 用作查询的一部分,只需将 MemberExpression 与相关的比较表达式包装起来,即

BinaryExpression eq = Expression.Equal(city, Expression.Constant("New York"));

// This will give us: item => item.Address[1].City == "New York"
Expression<Func<Employee, bool>> predicateLambda = Expression.Lambda<Func<Employee, bool>>(eq, param);

就您的代码而言:不确定为什么要创建一个委托类型为Func&lt;Line, bool&gt; 的lambda,而输入显然应为Employee。参数类型必须始终与委托签名匹配。

编辑

非数组索引器访问示例:

ParameterExpression param = Expression.Parameter(typeof(Employee), "item");
MemberExpression address = Expression.Property(param, "Address");

IndexExpression indexedAddress = Expression.MakeIndex(
    address,
    indexer: typeof(List<string>).GetProperty("Item", returnType: typeof(string), types: new[] { typeof(int) }),
    arguments: new[] { Expression.Constant(1) }
);

// Produces item => item.Address[1].
Expression<Func<Employee, string>> lambda = Expression.Lambda<Func<Employee, string>>(indexedAddress, param);

// Predicate (item => item.Address[1] == "Place"):
BinaryExpression eq = Expression.Equal(indexedAddress, Expression.Constant("Place"));
Expression<Func<Employee, bool>> predicateLambda = Expression.Lambda<Func<Employee, bool>>(eq, param);

【讨论】:

  • 感谢您的回复。要求略有变化。地址是 Employee 类中的 List 属性。
  • 我收到以下错误“System.Core.dll 中发生'System.ArgumentException' 类型的未处理异常”
  • 要求为 x.Address[1]=='Place' 生成查询。谢谢!!
  • 那是因为ArrayIndex 仅适用于数组(而非列表)。我会修改我的代码,我希望你能从那里得到它(此时还不清楚你将使用List&lt;string&gt; 生成什么样的谓词)。
  • 感谢您的澄清。已修改。
猜你喜欢
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多