2

I have the following dictionary:

Dictionary<string, PropertyInfo> filterProperties;

The content of this dictionary can be like this:

- "Language": [QueryData.Lang],
- "Id": [Querydata.UserId]

Each string key maps to a property of a my QueryData type.

Now let's suppose I have the following QueryData instance:

QueryData: { Lang= "en", UserId = "mcicero" }

Using the previous dictionary as example, I want to build the following expression:

e => e.Language == "en" && e.Id == "mcicero";

As you can see the dictionary keys are used for accesing the properties of e, and the dictionary values (QueryData properties) are used for specifying constants in the binary equal expressions.

e is of type Entity, and is guaranteed to have this properties.

The resulting expression should be of type Expression<Func<Entity, bool>>

How can I build this expression using recursion?

I say recursion because it sounds like a natural solution, but an iterative one would be preferred.

I tried the iterative alternative and ended up with an ugly and not so understandable code.

However, I am having trouble creating a recursion method for this problem.

7
  • you probably want to use dynamic linq. here's some info weblogs.asp.net/scottgu/… Commented Jul 10, 2015 at 13:04
  • 1
    You will probably need to look into Expression Trees. Commented Jul 10, 2015 at 13:06
  • Ignoring all the dictionary and QueryData stuff, you just want to know how to create an Expression like e => e.Language = "en" at runtime from a PropertyInfo and a string. Commented Jul 10, 2015 at 13:10
  • Can you explain it better, what you mean with build this expression ? Commented Jul 10, 2015 at 13:11
  • @StefanSteinegger Actually, I know how to create such expression, but I do not know how to join each mapped expression with an AND (&&) expression. The dictionary size can be variable Commented Jul 10, 2015 at 13:12

2 Answers 2

3

Leaving the creation of the individual expression to you, simply combine them together in an iterative loop:

// For an IEnumerable<Expression> in "expressions"
Expression left = null;
foreach(var right in expressions)
{
  if(left == null)
    left = right;
  else
    left = Expression.And(left, right);
}
// Combined expression is in "left"
// Don't forget it will be null if there were no expressions provided...

Or in one line with LINQ:

var expr = expressions.Aggregate(Expression.And);
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for that one line LINQ statement! Beautiful!
This &ing will result in a tree that is as deep as possible, which will reduce performance when there is a lot of nodes. You should try to build a tree as flat as possible, for example by putting them in a queue, taking out the first 2 elements, &ing them and putting at the end, until there is only 1 node left.
2

For the interested ones, in one single line:

Expression expr = filterProperties.Select(i => Expression.Equal(
                                                  Expression.Property(entityParameter, i.Key),
                                                  Expression.Constant(i.Value.GetValue(queryObj))
                                         )).Aggregate(Expression.And);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.