让我们假设我们需要查询一个实体列表,我们不知道这个标准是非常动态的,实体里面有字典和简单的字段让它成为下一个实体 - 地址(我只留下一个为简单起见的属性)。
public class Address
{
#region Public members
/// <summary>
/// The extra datafield values
/// </summary>
public IDictionary<string, string> DataFieldValues { get; set; }
public string City { get; set; }
#endregion
}
现在,如果我们在获得实现时查询名为 City 的固定字段:
private static Expression<Func<Address, bool>> BuildLambdaForAQueryItem(string caption, string value)
{
ParameterExpression param = Expression.Parameter(typeof(Address), caption);
BinaryExpression body = Expression.Equal(Expression.PropertyOrField(param, caption),
Expression.Constant(value,
typeof(Address).GetProperty(
caption).PropertyType));
return Expression.Lambda<Func<Address, bool>>(body, param);
}
现在,如果我想查询 DataFieldValue 集合,我也需要编写一个类似的 lambda:
x=>x.DataFieldValues.ContatinsKey(key) && DataFieldValues[key]==value 我用下面的方法得到的几乎是similar但它仍然没有正确应用过滤器:
private static Expression<Func<Address, bool>> BuildLambdaForAnExtraField(PostedQueryItem queryItem)
{
ParameterExpression dataFields = Expression.Parameter(typeof(Address), "x");
var dictionaryExpression = Expression.PropertyOrField(dataFields, "DataFieldValues");
var keyExists = Expression.Call(dictionaryExpression, "ContainsKey", null, Expression.Constant(queryItem.Caption));
Expression dictionaryAccessExpr = Expression.Property(dictionaryExpression, "Item",
Expression.Constant(queryItem.Caption));
var valueCorresponds = Expression.Equal(dictionaryAccessExpr, Expression.Constant(queryItem.Value));
return Expression.Lambda<Func<Address, bool>>(keyExists, dataFields).And(
Expression.Lambda<Func<Address, bool>>(valueCorresponds, dataFields));
}
最佳答案
我想你想使用 Expression.AndAlso
(短路 AND)在两个有问题的谓词表达式上构建表达式树的主体。
var body = Expression.AndAlso(keyExists, valueCorresponds);
return Expression.Lambda<Func<Address, bool>>(body, dataFields);
编辑:(如果您想坚持使用现有技术)
我的猜测是您的 And
方法是 LINQKit 的扩展方法图书馆。如果是这样,请注意,此扩展涉及使用第一个表达式的参数“调用”右侧表达式作为生成结果的一部分。如果您不能接受这一点(也许是 LINQ 提供程序限制?),您可以使用该库附带的有用的 Expand
扩展来“内联”调用的表达式。
return Expression.Lambda<Func<Address, bool>>(keyExists, dataFields)
.And(Expression.Lambda<Func<Address, bool>>(valueCorresponds, dataFields))
.Expand();
但在这种情况下,这是大规模的矫枉过正;我的建议是使用我的第一个样本。
关于c# - 动态编译 LINQ 查询以验证字典值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8212642/