Click here to Skip to main content
15,884,986 members
Articles / Programming Languages / C#

C# Filtering with JSON

Rate me:
Please Sign up or sign in to vote.
4.29/5 (6 votes)
16 Sep 2010CPOL1 min read 46.9K   608   12   4
Part 2 of creating a dynamical filtering mechanism in C#
filter.jpg

Introduction

In the first part, I presented a small JSON object model that can be used as a way to preserve the structure of a filter (used by jqGrid). In this second part, we'll take the model and convert it to a server-side filter.

Using the Code

So here are the entities behind the design:

C#
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; }
}

Using these classes, we can replicate any filter created on the client side. In terms of LINQ, the Rule is equivalent to a lambda expression and the Group class is equivalent to an expression tree. We can therefore write the methods that translate the model into System.Linq.Expressions.Expression:

From Rule to lambda expression:

C#
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;
}

From Group to expression tree:

C#
    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;
    }
}

I built a small helper called WebHelper to help me with the serialization and deserialization. To put it all in one, I also added the JSONToExpressionTree method that converts the serialized JSON into an expression tree.

So let's run some tests to see if it all goes well! We will need a simple domain:

C#
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; }
}

And a filter:

C#
Group g = new Group() { Operator = GroupOperator.And };
g.Rules.Add(new Rule() { Field = "Continent.Name", 
	Operator = RuleOperator.StartsWith, Data = "E" });

Conclusion

Hope you enjoyed this. The next article will merge the two in an easy to use application.

Link

Part 1 of creating a dynamical filtering mechanism in C#

History

  • 16th September, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
Romania Romania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey3-Feb-12 1:09
professionalManoj Kumar Choubey3-Feb-12 1:09 
Questioncool! but is a bug here? Pin
workingbird14-Jan-11 8:05
workingbird14-Jan-11 8:05 
AnswerRe: cool! but is a bug here? Pin
Anders Cui31-Mar-12 0:03
Anders Cui31-Mar-12 0:03 
Generalnice one Pin
Pranay Rana21-Dec-10 23:57
professionalPranay Rana21-Dec-10 23:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.