user3284063
user3284063

Reputation: 685

Creating tree from Expression

How can I create tree (graph) from System.Linq.Expressions.Expression?

I wish to have a graph (created from Expression) with nodes of a structure like

MyNode
{
    Expression _internalExpression = ...
    MyNode Parent {get ...} 
    IEnumerable<MyNode> Children {get ...}
}

I thought about deriving from ExpressionVisitor but I don't know how to infer the parent-child relation from within method being called (Visit, VisitBinary etc. ).

Update: Probably I wasn't explicit enough - I wish to have a code that takes a Linq (in the expression form, so no curly brackets) and gives me back a composite data structure with components that I have described above ( class MyNode { ...} ).

So it should work like this:

MyNode root = TreeCreator.FromExpression((x,y) => x + y);

The ExpressionVisitor traverses the Expression tree and invokes Visit method on every node encountered - that's ok. Unfortunately, it takes only single parameter (Expression) so I don't know in what context (under which parent) it is working. If it had a signature like Visit(Expression parent, Expression child), then it would be easy to build the tree of MyNode nodes by overriding the Visit method.

Upvotes: 0

Views: 316

Answers (1)

Servy
Servy

Reputation: 203815

It is far easier to traverse a graph that is defined in a manner comparable to what you have described in your question than it is to try to traverse an Expression tree. If you have an object that has an IEnumerable representing it's children, like so:

class MyNode
{
    MyNode Parent { get; private set; }
    IEnumerable<MyNode> Children { get; private set; }
}

Then to traverse it you only need a few lines of code:

public static IEnumerable<T> Traverse<T>(
    this IEnumerable<T> source
    , Func<T, IEnumerable<T>> childrenSelector)
{
    var stack = new Stack<T>(source);
    while (stack.Any())
    {
        var next = stack.Pop();
        yield return next;
        foreach (var child in childrenSelector(next))
            stack.Push(child);
    }
}

We can now write:

IEnumerable<MyNode> nodes = GetNodesFromSomewhere();
var allNodesInTree = nodes.Traverse(node => node.Children);

And this requires none of the messiness of trying to pretend that this node graph represents code expressions when it doesn't.

Upvotes: 2

Related Questions