【问题标题】:Dynamically compiling LINQ queries to verify a dictionary value动态编译 LINQ 查询以验证字典值
【发布时间】:2011-11-21 13:34:45
【问题描述】:

让我们假设我们需要查询一个实体列表,并且我们不知道几乎是动态的标准,并且实体内部既有字典也有简单字段让这成为下一个实体 - 地址(我只留下一个为简单起见的属性)。

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

【问题讨论】:

    标签: c# .net linq dictionary lambda


    【解决方案1】:

    我认为您想在两个谓词表达式上使用Expression.AndAlso(短路与)来构造表达式树的主体。

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

    但在这种情况下,这大量矫枉过正;我的建议是使用我的第一个样本。

    【讨论】:

    • 你说得对,谢谢。但是我还是不明白为什么我之前的实现没有成功
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    相关资源
    最近更新 更多