Your lambda example,
p => p.MarketId == marketId && p.FirstName == "John" || p.FirstName == "Jack"
is equivalent
p => (p.MarketId == marketId && p.FirstName == "John") || p.FirstName == "Jack"
since && has higher precision than || .
Because of this, you get a tree with && at the bottom (as you need to calculate it first), and then || on top:
|| / \ && Firstname == "Jack" / \ p.MarketId == marketId p.FirstName == "John"
Once you understand the priority of the operator, this makes sense. If you want to use an alternative, you can simply use parentheses to first evaluate || (so that it hits the bottom of the expression tree).
p => p.MarketId == marketId && (p.FirstName == "John" || p.FirstName == "Jack")
Your common problem is that you are approaching this a little wrong. You are currently trying to create 2 groups, one for OR and one for AND. This may work in this case, but not in general, for example, what would you do for this: (a && b) || (c && d) (a && b) || (c && d) ?
I think that something should happen that everyone, and everyone, or should translate into their own group of predicates. See the βMultiple Compound Predicates (Predicate Group)β section of your related article. You simply replace BinaryExpression with a predicate group.
In your example, you have (a && b) || c with || on the top. What you want in the end is every time you have an operator that you want to create a predicate group with a left and right list of expressions. In your logic, to convert a binary expression to a predicate group, you must first use the same function to convert the left and right to the predicate group
i.e. your code sees ||.
he creates a group of predicates ready to add expressions to his list
he first selects the left one (it doesn't matter).
ok, left is another binary expression, so it calls itself to get a predicate group that your target library understands so that recursion only works with && b. First, he selects the left one, sees a simple predicate, which means that he can just add it to the predicate group, he does the same for the correct one, then we return to the original function call, which now has the predicate group, the lower expression on the left is converted to another predicate group and is added. he goes right now, which is a simple individual predicate, and therefore he can add it to his list.
Okay, so if I had something crazy, for example: a && b || c || d && e a && b || c || d && e
Well, given the higher priority, we get the following: ((a && b) || c) || (d && e) ((a && b) || c) || (d && e) note that I am not 100% sure that either c with the first && or the last will be added in the bracket, but it does not matter, the logic is the same. When rendering the tree, start with the innermost brackets. These are the βleavesβ, then work outward using the brackets to process the tree, and finally, reaching the root of the node, which in our case is equal to || to the right of c:
|| / \ || && / \ / \ && cde / \ ab