使用 JSON 进行 C# 过滤
创建动态过滤机制的 C# 第二部分。

引言
在第一部分中,我介绍了一个小的 JSON 对象模型,它可以用来保存过滤器的结构(jqGrid 使用)。 在这第二部分中,我们将该模型转换为服务器端过滤器。
Using the Code
所以,这是设计背后的实体
public class Group
{
public GroupOperator Operator { get; set; }
public List<Rule> Rules { get; set; }
public List<Group> Groups { get; set; }
}
public class Rule
{
public string Field { get; set; }
public RuleOperator Operator { get; set; }
public string Data { get; set; }
}
使用这些类,我们可以复制客户端创建的任何过滤器。 在 LINQ 方面,Rule 等效于 lambda 表达式,Group
类等效于表达式树。 因此,我们可以编写将模型转换为 System.Linq.Expressions.Expression
的方法。
从 Rule 到 lambda 表达式
public Expression ToExpression(Type parameterType, ParameterExpression param) {
// get the property that will be evaluated
PropertyInfo pi = null;
MemberExpression member = null;
if (this.Field.Contains(".")) // check for subproperties
{
....
}
else {
pi = parameterType.GetProperty(this.Field);
member = Expression.PropertyOrField(param, this.Field);
}
ConstantExpression constant = this.Operator == RuleOperator.IsNull ||
this.Operator == RuleOperator.NotNull
? Expression.Constant(null, pi.PropertyType)
: Expression.Constant(this.CastDataAs(pi.PropertyType), pi.PropertyType);
switch(this.Operator) {
case RuleOperator.IsNull: // it's the same for null
case RuleOperator.Equals:
return Expression.Equal(member, constant);
....
}
return null;
}
从 Group 到表达式树
public Expression<func><t, bool> ToExpressionTree<t>(){
Type t = typeof(T);
// create a parameter expression that can be passed to the rules
ParameterExpression param = Expression.Parameter(t, "p");
// get the expression body. This consists of all subgroups and rules
Expression body = GetExpressionFromSubgroup(this, t, param);
if (body == null)
return null;
else
return Expression.Lambda<func<t, bool>>(
body,
new ParameterExpression[] { param }
);
}
protected Expression GetExpressionFromSubgroup
(Group subgroup, Type parameterType,ParameterExpression param) {
Expression body = null;
.....
return body;
}
}
我构建了一个名为 WebHelper
的小助手来帮助我进行序列化和反序列化。 为了将所有内容放在一起,我还添加了 JSONToExpressionTree
方法,该方法将序列化的 JSON 转换为表达式树。
所以让我们运行一些测试,看看一切是否正常! 我们需要一个简单的领域
public class Country {
public Country() { }
public int Id { get; set; }
public string Name { get; set; }
public Continent Continent { get; set; }
}
public class Continent {
public Continent() { }
public string Name { get; set; }
public IList<country> Countries { get; set; }
}
和一个过滤器
Group g = new Group() { Operator = GroupOperator.And };
g.Rules.Add(new Rule() { Field = "Continent.Name",
Operator = RuleOperator.StartsWith, Data = "E" });
结论
希望你喜欢这篇文章。 下一篇文章会将两者合并到一个易于使用的应用程序中。
链接
历史
- 2010 年 9 月 16 日:初始发布