【问题标题】:How can I change already created Expression?如何更改已创建的表达式?
【发布时间】:2016-09-23 08:52:34
【问题描述】:

我有以下课程:

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

我将IEnumerable<Entity>> 作为数据源传递给剑道网格(我认为这无关紧要,但为了清晰起见,在此处添加)。

我想实现服务端过滤,已经在页面实现了单独的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 库的DataSourceRequest 类型。 item.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 而无需重新创建新的?

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

【问题讨论】:

  • 不,表达式树在设计上是不可变的。
  • @JonSkeet 好的,那么遍历这个表达式树并将一些节点复制到新的表达式树并用另一个替换一些节点呢?有可能吗?

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


【解决方案1】:

根据@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);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多