65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 JSON 进行 C# 过滤

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.29/5 (6投票s)

2010年9月16日

CPOL

1分钟阅读

viewsIcon

48291

downloadIcon

624

创建动态过滤机制的 C# 第二部分。

filter.jpg

引言

第一部分中,我介绍了一个小的 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" });

结论

希望你喜欢这篇文章。 下一篇文章会将两者合并到一个易于使用的应用程序中。

链接

创建 C# 中动态过滤机制的第一部分。

历史

  • 2010 年 9 月 16 日:初始发布
© . All rights reserved.