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

Column Mapping Using Expressions and Dictionary

我在为 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 应用到我在扩展 class:

中的查询
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 做同样的事情但是为了过滤一个 IQueryable 对象,我需要一个不同的表达式来表示方法 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;
}

问题是如何在 ApplyFiltering 方法中使用我的 columnsMap?或者我应该为此更改我的 columnsMap 吗?

很简单。唯一的问题是当你有一个值类型列(例如 intboolDateTime 时)...... Expression<Func<Industry, object>> 将引入装箱field/property 到 object 我们必须删除。此问题已存在 string 秒。

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