我有以下课程:
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库的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
?
如果是,你能否提供修改的示例代码,因为我不知道应该从哪个开始。
答案 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);
产生所需的结果。所以,我希望它会帮助别人。