Skip to content

Recorrer árboles y navegar ​

TreeTraversal pertenece a Greencore.Platform.Errors.Trees y funciona sin Result. Usa las consultas de Error para búsquedas habituales; usa el recorrido cuando necesitas ramas, hojas o rutas completas.

Árbol del ejemplo ​

csharp
using System;
using System.Linq;
using Greencore.Platform.Errors;
using Greencore.Platform.Errors.Extensions;
using Greencore.Platform.Errors.Trees;
using Greencore.Platform.Nodes;

var error = Error.Create("Importación fallida.");
var fila = error.AddReason(new Reason("Fila inválida."));
fila.AddReason(new Reason("Nombre obligatorio."));
fila.AddReason(new Reason("Correo inválido."));
error.WithReason("Archivo incompleto.");
var traversal = new TreeTraversal();

Los bloques siguientes continúan este ejemplo.

Métodos públicos ​

MétodoResultadoNodo inicial
EnumerateNodes(IErrorNode)IEnumerable<INode>Incluido
EnumerateDescendants(INode)IEnumerable<INode>Excluido
EnumerateLeaves(IErrorNode)IEnumerable<INode> de hojasIncluido si es hoja
EnumerateLeafPaths(IErrorNode)IEnumerable<IReadOnlyList<INode>>Incluido en cada ruta
EnumerateLeafPaths(INode)Lo mismo, desde cualquier nodoIncluido en cada ruta
TreeTraversal.Children(INode)IReadOnlyList<INode> de hijos inmediatosExcluido

INode expone Message y Metadata; no declara Reasons. Usa Children para obtener hijos sin distinguir IErrorNode de IReasonNode. Si no implementa ninguno de esos dos contratos, devuelve una lista vacía.

Recorrer nodos y ramas ​

csharp
foreach (var nodo in traversal.EnumerateNodes(error))
    Console.WriteLine(nodo.Message);

var primeraCausaDeFila = traversal.EnumerateDescendants(fila)
    .OfType<IReasonNode>()
    .FirstOrDefault();

Console.WriteLine(primeraCausaDeFila?.Message.ToString()); // Nombre obligatorio.
Console.WriteLine(TreeTraversal.Children(error).Count); // 2.

El primer bucle imprime la raíz, la fila, el nombre, el correo y el archivo, en ese orden. El recorrido visita cada nodo antes de descender por sus hijos y respeta el orden de Reasons. error.Reasons y Children(error) solo muestran el nivel inmediato.

Rutas hasta las hojas ​

csharp
foreach (var ruta in traversal.EnumerateLeafPaths(error))
    Console.WriteLine(string.Join(" → ", ruta.Select(nodo => (string)nodo.Message)));
text
Importación fallida. → Fila inválida. → Nombre obligatorio.
Importación fallida. → Fila inválida. → Correo inválido.
Importación fallida. → Archivo incompleto.

Cada ruta es una lista independiente de solo lectura con referencias a los nodos originales. Una raíz sin hijos produce una ruta de un elemento. Puedes pasar fila para obtener rutas que comiencen en esa razón.

Las enumeraciones son diferidas. Siguen Reasons, no Parent, y conservan apariciones compartidas por distintas rutas. El recorrido corta repeticiones de un nodo en la misma rama para evitar ciclos; esto no equivale a deduplicar globalmente el árbol.

Subir al padre y a la raíz propietaria ​

csharp
INode padre = fila.Up();
Error raiz = fila.Root();

Console.WriteLine(ReferenceEquals(padre, error)); // True.
Console.WriteLine(ReferenceEquals(raiz, error)); // True.

Up() devuelve el padre inmediato: INode en una razón dinámica, o TParent en una razón tipada. Lanza InvalidOperationException si no hay padre.

Root() se ofrece sobre IReasonNode y sigue Parent hasta un Error. Lanza InvalidOperationException si no llega a un error.

Una referencia no cambia la pertenencia. Por eso, al recorrer un error agregado o un error que referencia una razón, Root() puede devolver la raíz original y no el error desde el que iniciaste el recorrido. Usa EnumerateLeafPaths para conservar el contexto de la consulta. Consulta referencias de errores.

Sustitución de TreeQuery ​

La API actual no contiene TreeQuery. Sobre un error usa error.FindReason<T>(), HasReason<T>() o TryGetReason<T>(). Sobre una razón usa EnumerateDescendants con LINQ, como en el ejemplo de la fila.

Uso personal limitado. Uso comercial sujeto a autorización escrita.