如何更改已创建的表达式?
How can I change already created Expression?
我有点关注class:
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
而无需重新创建新的?
如果是,能不能提供一下修改的示例代码,我也不知道从何入手。
根据@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);
生成所需的结果。所以,我希望它能对某人有所帮助。
我有点关注class:
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
而无需重新创建新的?
如果是,能不能提供一下修改的示例代码,我也不知道从何入手。
根据@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);
生成所需的结果。所以,我希望它能对某人有所帮助。