代码之家  ›  专栏  ›  技术社区  ›  AliReza Sabouri

使用表达式和字典的列映射

  •  1
  • AliReza Sabouri  · 技术社区  · 7 年前

    我在为 IQueryable 反对我无法找到正确的方法来使用表达式将字符串映射到对象属性。

    这是我的查询对象和映射字典:

    var query = context.Industries.AsQueryable();
    var columnsMap = new Dictionary<string, Expression<Func<Industry, object>>>()
                {
                    ["name"] = v => v.Name,
                    ["isicCode"] = v => v.IsicCode.Data,
                    ["isicCodeTitle"] = v => v.IsicCode.Title,
                    ["isActive"] = v => v.IsActive,
                };
    

    我在用 columnsMap 应用词典 Orderby 对于我在扩展类中的查询:

    public static IQueryable<T> ApplyOrdering<T>(this IQueryable<T> query, IQueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
    {
        if (String.IsNullOrWhiteSpace(queryObj.SortBy) || !columnsMap.ContainsKey(queryObj.SortBy))
            return query;
        if (queryObj.IsSortAsc)
            return query.OrderBy(columnsMap[queryObj.SortBy]);
        else
            return query.OrderByDescending(columnsMap[queryObj.SortBy]);
    }
    

    没关系的 OrderBy 但我也要做同样的事 ApplyFiltering 但对于过滤器 可液化的 对象我需要一个不同的where方法表达式 Expression<Func<T, bool>>

    public static IQueryable<T> ApplyFiltering<T>(this IQueryable<T> query, IQueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
    {           
        query.Where(columnsMap['name'] == "test Name"); //this is the problem. 
        return query;
    }
    

    问题是如何在应用过滤方法中使用columnsMap或者我应该为此改变我的专栏主页吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   xanatos    7 年前

    很简单。唯一的问题是当您有一个值类型列(一个 int 或A bool 或者 DateTime 例如…一个 Expression<Func<Industry, object>> 将介绍一个领域的拳击/属性 object 我们必须移除。这个问题是不存在的 string s。

    // isActive is a bool
    Expression<Func<Industry, object>> exp = columnsMap["isActive"];
    object value = true; // You can't use "true" (string) here! isActive is a bool
    
    // Other exammple
    // Expression<Func<Industry, object>> exp = columnsMap["name"];
    // object value = "Foo";
    
    var body = exp.Body;
    
    // Remove the boxing for value types
    if (body.NodeType == ExpressionType.Convert)
    {
        body = ((UnaryExpression)body).Operand;
    }
    
    var eq = Expression.Equal(body, Expression.Constant(value, body.Type));
    
    var exp2 = Expression.Lambda<Func<T, bool>>(eq, exp.Parameters);
    
    return query.Where(exp2);
    

    使用示例 string value 以下内容:

    Expression<Func<Industry, object>> exp = columnsMap["isActive"];
    string value = "true";
    // Other exammple
    //Expression<Func<Industry, object>> exp = columnsMap["name"];
    //string value = "Foo";
    
    var body = exp.Body;
    
    // Remove the boxing for value types
    if (body.NodeType == ExpressionType.Convert)
    {
        body = ((UnaryExpression)body).Operand;
    }
    
    object value2 = value;
    
    if (value2 != null && body.Type != value2.GetType())
    {
        value2 = Convert.ChangeType(value2, body.Type);
    }
    
    var eq = Expression.Equal(body, Expression.Constant(value2, body.Type));
    
    var exp2 = Expression.Lambda<Func<Industry, bool>>(eq, exp.Parameters);
    
    return query.Where(exp2);