数组属性过滤器的动态lambda表达式

时间:2015-12-06 13:35:57

标签: c# linq lambda

根据要求,我想使用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);

但它不起作用。

任何帮助将不胜感激。

感谢。

1 个答案:

答案 0 :(得分:2)

您的“动态查询”表达式(实际上不是查询,它是一个简单的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<Line, bool>时,不确定为什么要创建一个委托类型为Employee的lambda。参数类型必须始终与委托签名匹配。

修改

非数组索引器访问示例:

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);