如何更改已创建的表达式?

时间:2016-09-23 08:52:35

标签: c# asp.net-mvc lambda kendo-asp.net-mvc

我有以下课程:

public class Entity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

我将IEnumerable<Entity>>作为数据源传递给kendo网格(我认为这无关紧要,但在此处添加了问题的可清除性)。

我想实现服务器端过滤,并在页面上实现了单独的input[text]字段,并通过以下方式在客户端添加过滤器:

var grid = $(e).data('kendoGrid');
var columns = grid.columns;
var columnTypes = grid.dataSource.options.schema.model.fields;
for (var i = 0; i < columns.length; i++) {
    if (columns[i].field) {
        var columnDataType = columnTypes[columns[i].field].type;
        if (columnDataType == 'number' && !isNaN(Number(value))) {
            var filter = { field: columns[i].field, operator: "eq", value: Number(value) };
        } else if (columnDataType == 'string') {
            var filter = { field: columns[i].field, operator: "contains", value: value };
        }

        gridListFilter.filters.push(filter);
    }
}

var gridDataSource = grid.dataSource;
console.log(gridListFilter);
gridDataSource.filter(gridListFilter);

在服务器端,我实现了以下算法,用于在虚拟化处理程序方法中进行过滤:

IQueryable<Entity> query = this.GetQuery<Entity>();
foreach (var item in dataSourceRequest.Filters)
{
    var paramExpr = Expression.Parameter(typeof(TReturnType), "item");
    var expr = item.CreateFilterExpression(paramExpr);
    var lambda = Expression.Lambda<Func<TReturnType, bool>>(expr, paramExpr);
    query = query.Where(lambda);
}

其中dataSourceRequest的类型为来自telerik库的DataSourceRequestitem.CreateFilterExpression生成BinaryExpression以下表示的事项:

item => (IIF((item != null), item.Id, 0) == 6999142) OrElse 
((IIF((item != null), item.Name, null) ?? "").ToLower().Contains("6999142".ToLower()))

其中“6999142”是我从input[text]查看的搜索字符串。我想以下列方式修改此表达式:

item => (IIF((item != null), item.Id, 0).ToString().Contains("6999142")) OrElse 
((IIF((item != null), item.Name, null) ?? "").ToLower().Contains("6999142".ToLower()))

有没有办法在不重新创建新版本的情况下更改已创建的Expression

如果是,你能否提供修改的示例代码,因为我不知道应该从哪个开始。

1 个答案:

答案 0 :(得分:2)

根据@ JonSkeet的评论,我已实施以下

internal class KendoExpressionModifier : ExpressionVisitor
{
    public Expression Modify(Expression expression)
    {
        return Visit(expression);
    }

    protected override Expression VisitConditional(ConditionalExpression node)
    {
        //converting result of conditional expression to string
        return Expression.Call(node.IfTrue, typeof(object).GetMethod("ToString"));
    }

    protected override Expression VisitBinary(BinaryExpression node)
    {
        //replacing '==' operator with '.Contains'
        if (node.NodeType == ExpressionType.Equal)
        {
            var left = this.Visit(node.Left);
            var right = this.Visit(node.Right);

            return Expression.Call(left, typeof(string).GetMethod("Contains"), right);
        }
        //replacing expression 'a.ToString() ?? ""' with 'a != null ? a.ToString() : ""'
        else if (node.NodeType == ExpressionType.Coalesce)
        {
            var left = this.Visit(node.Left) as MethodCallExpression;

            return Expression.Condition(
                Expression.MakeBinary(
                    ExpressionType.NotEqual, 
                    left.Object, 
                    Expression.Constant(null)), 
                left, 
                Expression.Constant(string.Empty));
        }

        return base.VisitBinary(node);
    }

    protected override Expression VisitConstant(ConstantExpression node)
    {
        //replacing constant numeric value with its string representation
        if (node.Value.GetType() != typeof(string))
        {
            return Expression.Call(node, typeof(object).GetMethod("ToString"));
        }

        return base.VisitConstant(node);
    }
}

调用此修饰符:

var kendoExpressionModifier = new KendoExpressionModifier();
expr = kendoExpressionModifier.Modify(expr);

产生所需的结果。所以,我希望它会帮助别人。