如何从System.Linq.Expressions.Expression创建树(图)?
我希望有一个图表(使用Expression创建),其结构类似于
MyNode
{
Expression _internalExpression = ...
MyNode Parent {get ...}
IEnumerable<MyNode> Children {get ...}
}
我想过从ExpressionVisitor派生,但我不知道如何推断父子关系 从方法中调用(Visit,VisitBinary等)。
更新: 可能我不够明确 - 我希望有一个采用Linq的代码(在表达式中,所以没有花括号) 并给我一个复合数据结构,其中包含我上面描述的组件(类MyNode {...})。
所以它应该像这样工作:
MyNode root = TreeCreator.FromExpression((x,y) => x + y);
ExpressionVisitor遍历Expression树并在遇到的每个节点上调用Visit方法 - 没关系。不幸的是,它只需要单个参数 (表达式)所以我不知道它在什么情况下(在哪个父项下)。如果它有像Visit(Expression parent,Expression child)这样的签名,那么它会很容易 通过重写Visit方法构建MyNode节点树。
答案 0 :(得分:2)
远更容易遍历以与您在问题中描述的方式相比的方式定义的图形,而不是尝试遍历Expression
树。如果你有一个IEnumerable
代表它的孩子的对象,就像这样:
class MyNode
{
MyNode Parent { get; private set; }
IEnumerable<MyNode> Children { get; private set; }
}
然后遍历它你只需要几行代码:
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);
}
}
我们现在可以写:
IEnumerable<MyNode> nodes = GetNodesFromSomewhere();
var allNodesInTree = nodes.Traverse(node => node.Children);
这不需要尝试假装此节点图表示代码表达式时不会出现混乱。