Skip to content

Enumerar errores y razones ​

Las tres enumeraciones pertenecen a Greencore.Platform.Errors.Extensions.

MétodoTipo permitidoIncluye la raízFiltro predeterminado
ErrorsOfType<T>(bool includeNonTerminal = false)T : ErrorSí, si coincideSolo hojas
ReasonsOfType<T>(bool includeNonTerminal = false)T : class, INodeNoSolo hojas
NodesOfType<T>(bool includeNonTerminal = false)T : class, INodeSí, si coincideSolo hojas

Una hoja es un nodo sin hijos. Ser hoja no depende de si el nodo es un error o una razón.

Comparar hojas y todos los niveles ​

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

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

Console.WriteLine(error.ErrorsOfType<Error>().Count()); // 0.
Console.WriteLine(error.ErrorsOfType<Error>(true).Count()); // 1.
Console.WriteLine(error.ReasonsOfType<IReasonNode>().Count()); // 3.
Console.WriteLine(error.ReasonsOfType<IReasonNode>(true).Count()); // 4.
Console.WriteLine(error.NodesOfType<INode>().Count()); // 3.
Console.WriteLine(error.NodesOfType<INode>(true).Count()); // 5.

foreach (var hoja in error.ReasonsOfType<IReasonNode>())
    Console.WriteLine(hoja.Message);

Salida del recorrido de hojas:

text
Nombre obligatorio.
Correo inválido.
Archivo incompleto.

La raíz tiene razones, por eso ErrorsOfType<Error>() está vacío. Esto no significa que el diagnóstico carezca de error: HasError<Error>() sigue siendo verdadero.

Si la raíz no tiene hijos, ErrorsOfType<Error>() y NodesOfType<INode>() la devuelven, mientras que ReasonsOfType<INode>() está vacío.

Filtrar y materializar ​

csharp
var todas = error.ReasonsOfType<IReasonNode>(includeNonTerminal: true);
var conMetadatos = todas.Where(razon => razon.Metadata.Count > 0).ToArray();
var mensajes = todas.Select(razon => (string)razon.Message).ToArray();

Son secuencias diferidas: el árbol se recorre al consumirlas. ToArray() o ToList() evita repetir el recorrido y captura las referencias encontradas en ese momento; no clona los nodos ni sus metadatos. No modifiques la estructura durante la enumeración ni asumas que proporciona una instantánea segura frente a escrituras concurrentes.

Referencias compartidas ​

Los recorridos siguen las relaciones Reasons y conservan las apariciones por ruta. Una misma instancia compartida puede aparecer varias veces. Si tu operación necesita instancias únicas:

csharp
var unicos = error.NodesOfType<INode>(includeNonTerminal: true)
    .Distinct(System.Collections.Generic.ReferenceEqualityComparer.Instance)
    .ToArray();

Eliminar duplicados pierde información sobre las distintas rutas. Para mostrar el contexto de cada aparición utiliza EnumerateLeafPaths.

Consultar todos los errores de un agregado ​

csharp
var primero = Error.Create("Fallo de stock.").WithReason("Sin unidades.");
var segundo = Error.Create("Fallo de pago.").WithReason("Tarjeta vencida.");
var combinado = ErrorComposer.Combine(primero, segundo);

var errores = combinado.ErrorsOfType<Error>(includeNonTerminal: true).ToArray();
Console.WriteLine(errores.Length); // 3: raíz agregada y dos errores.

Para excluir la raíz agregada y conservar los errores con razones, usa combinado.ReasonsOfType<Error>(includeNonTerminal: true). El nombre «razones» expresa aquí su posición descendiente.

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