3

There are two ways to construct an expression tree in C#:

  1. let the compiler rewrite a lambda and store the result;
  2. construct it piecewise, calling factory methods provided by the Expression class.

The first approach is simple, but it doesn't let me integrate already existing subexpressions into a resulting expression, which is my main goal. (These subs are passed to me as function parameters by design).

In fact, the second approach itself is the subexpression composition process, but it is very cumbersome for anything but the simplest expressions with little to no nesting involved.

So, to get the best of two ways, while having to construct the trees piecewise, I look at copiler-generated expressions, and use them as hints. What I do is: write the code to construct a tree, while looking at the given tree. The whole process is quite a routine, so I wonder:

  • are there tools to automate that? Couldn't find any myself.
  • aside from codegens, are there some other possibilities to improve my method and make it more productive?

Here's the explaination of why I need this strange process at all.

Expression<Func<IEnumerable<N>, IEnumerable<N>, IEnumerable<N>>>
    MyExpression = (src1, src2) => 
        src1.SelectMany(outer => lookup[outer.Value1].Select(
                inner => new N(outer, inner)));

Now, I am provided with two subexpressions, which are to be placed instead of outer.Value1 and new N(outer, inner). I can't use .Compile() and utilise them as lambdas, because I have to provide the complete expression tree for further processing intact. I need a way to integrate them into MyExpression, and the only method I'm aware of is to construct the whole tree via Expression factories. But with more complex queries it gets extremely complex and error-prone.

4
  • I don’t understand your question. You want something that converts lambda expressions into code that creates expressions? Why? Give an actual example of what you’re trying to solve please. Commented Aug 9, 2014 at 16:35
  • Build your own parser that builds trees? See my SO answer: stackoverflow.com/a/25106688/120163 Commented Aug 9, 2014 at 16:45
  • @poke so that I could edit them, of course =) I need it for a Linq library which is heavily expression-based, and the compositions are quite bulky sometimes. Commented Aug 9, 2014 at 16:54
  • @IraBaxter Yep, I consider writing one... But it will require me to study the subject a bit more, so I decided to ask first. Commented Aug 9, 2014 at 16:56

1 Answer 1

2

aside from codegens, are there some other possibilities to improve my method and make it more productive?

Basically you'd want to write a class that extends ExpressionVisitor that replaces some component of one expression with pieces from the other expression.

are there tools to automate that?

LINQKit does just that. From the website's examples:

Expression<Func<Purchase,bool>> criteria1 = p => p.Price > 1000;
Expression<Func<Purchase,bool>> criteria2 = p => criteria1.Invoke (p)
                                             || p.Description.Contains ("a");

Console.WriteLine (criteria2.Expand().ToString());

Output:

p => ((p.Price > 1000) || p.Description.Contains("a"))

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! Looks like a solution, I'll dig into it now. The only concern for now is that LINQKit depends on EntityFramework (at least that's what NuGet says). The project I work on is a lightweight library, which would rarely be used with EF, and making its users depend on EF is an overkill...
@vines The original LINQKit (which you can download from the author's site) doesn't require EF. The maintainer of the NuGet package suggested to me to use an older version of it if you don't want that dependency on EF 6.

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.