1.         sealed class Dumper
  2.         {            
  3.             public static string Dump(Node root)
  4.             {
  5.                 // get all nodes (used later for "to parent" iteration
  6.                 var allNodeTuples = EnumerateNodes(root, null);
  7.                 // main query, later we'll agregate results
  8.                 var query = allNodeTuples.Select(tuple =>
  9.                 {
  10.                     var node = tuple.Item1;
  11.                     var parent = tuple.Item2;
  12.                     var s = new List<string> {node.Text, Environment.NewLine};
  13.                     if (parent != null)
  14.                     {
  15.                         // thats for 'closest' childs
  16.                         s.Insert(0, parent.Children.Last() != node ? "├" : "└");
  17.                         s.Insert(1,"-");
  18.                         do
  19.                         {
  20.                             // build indention
  21.                             node = parent;
  22.                             var oldParent = parent;
  23.                             parent = allNodeTuples.Where(t => t.Item1 == oldParent).FirstOrDefault().Item2;
  24.                             if (parent != null)                            
  25.                                 s.Insert(0, (parent.Children.Last() != node
  26.                                                  ? "│ "
  27.                                                  : "  "));                            
  28.                         } while (parent != null);
  29.                     }
  30.                     // joins results into single line
  31.                     return string.Join(String.Empty,s);
  32.                 });                
  33.                 // run query with string builder to aggregate
  34.                 return query.Aggregate(new StringBuilder(), (s, v) => s.Append(v)).ToString();
  35.             }
  36.  
  37.             // Enumerate all tree nodes, returning tuple with first item as node, second as node's parent
  38.             private static IEnumerable<Tuple<Node,Node>> EnumerateNodes(Node root, Node parent)
  39.             {
  40.                 /* recursive:
  41.                 yield return new Tuple<Node,Node>(root, parent);
  42.                 foreach (var child in root.Children)
  43.                     foreach (var sub in EnumerateNodes(child, root)) yield return sub;*/                                
  44.                 var workStack = new Stack<Tuple<Node,Node>>();
  45.                 workStack.Push(new Tuple<Node, Node>(root, parent));
  46.                 while (workStack.Count>0)
  47.                 {
  48.                     var current = workStack.Pop();
  49.                     yield return current;
  50.                     foreach (var child in current.Item1.Children.Reverse())
  51.                         workStack.Push(new Tuple<Node, Node>(child, current.Item1));
  52.                 }
  53.             }          
  54.         }