Click here to Skip to main content
Click here to Skip to main content

C# Filtering with JSON

, 16 Sep 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

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:

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:

    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:

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:

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)

Share

About the Author

strofo
Engineer
Romania Romania
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermanoj kumar choubey3-Feb-12 2:09 
Questioncool! but is a bug here? Pinmemberworkingbird14-Jan-11 9:05 
AnswerRe: cool! but is a bug here? PinmemberAnders Cui31-Mar-12 1:03 
Generalnice one PinmemberPranay Rana22-Dec-10 0:57 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 16 Sep 2010
Article Copyright 2010 by strofo
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid