Skip to content

Diagnósticos, reportes y evidencia ​

Índice · Motivación · Anterior: planes · Siguiente: formularios

La evaluación y el diagnóstico tienen funciones distintas. RuleEvaluation registra qué ocurrió al ejecutar la composición. RuleDiagnostic añade código, mensaje y detalles para explicar un incumplimiento. Un plan realiza ambas etapas y devuelve ValidationReport.

Problema que resuelve ​

El motor necesita conservar estados, omisiones y evidencia; una UI necesita mensajes por campo y una API puede necesitar códigos estables. Publicar directamente toda la traza mezclaría información técnica con comunicación de usuario. La proyección de diagnósticos permite que ambas vistas provengan de la misma ejecución sin tratarlas como si fueran equivalentes.

Consulta los diagnósticos para presentar incumplimientos funcionales. Consulta la evaluación cuando necesites explicar el recorrido o depurar la composición. No conviertas excepciones técnicas ni cancelaciones en diagnósticos funcionales.

Proyección de incumplimientos ​

RuleDiagnosticDefinition contiene un código no vacío y un mensaje fijo o un formateador Func<RuleEvaluation, string>. El resultado del formateador también debe ser no vacío. RuleDiagnostics asocia estas definiciones con NodeId y proyecta únicamente evaluaciones insatisfechas.

Una alternativa satisfecha hace que AnyOf sea satisfactorio. Los fallos de alternativas probadas antes no se publican como errores del reporte, aunque una evaluación con Trace pueda conservarlos para inspección.

Una negación fallida utiliza su mensaje propio. No proyecta como errores los hijos que hicieron verdadera la condición negada. Los grupos sin diagnóstico propio permiten que sus diagnósticos hijos asciendan en la proyección.

Al construir el plan se exigen diagnósticos para hojas publicables, AnyOf y Not. La condición de When no necesita mensaje de fallo, porque determina aplicabilidad. El contenido negado tampoco necesita diagnósticos para la proyección de Not.

Reporte y validez ​

ValidationReport contiene Evaluation y Diagnostics. IsValid equivale a Evaluation.Status != RuleStatus.Unsatisfied. Por tanto, una raíz omitida se considera válida en el sentido de que no hay un incumplimiento aplicable. Si la presencia es obligatoria, debe existir una condición que la exija.

RuleDiagnostic conserva la evaluación, el código, el mensaje y sus hijos. Path se obtiene de la evaluación. IsGroup indica si el tipo de nodo es distinto de Leaf.

Elegir una vista ​

ConsultaInformación entregada
EnumerateDiagnostics()Recorre grupos y detalles en profundidad
EnumerateDiagnostics(false)Devuelve diagnósticos sin hijos
ForField("Email")Devuelve diagnósticos terminales con esa ruta exacta
ForField("Email", DiagnosticView.Summary)Primer mensaje asociado al campo en cada rama, sin repetir sus descendientes
ForField("Email", DiagnosticView.Details)Diagnósticos terminales del campo
ForField("Email", DiagnosticView.All)Grupos y detalles del campo

También puedes usar report.ForField((Customer x) => x.Email, DiagnosticView.Summary). La expresión se convierte en ruta, no se ejecuta contra el candidato.

Un grupo sin hijos diagnósticos, como un Not fallido, se conserva en Details. Aquí «terminal» significa sin detalles, no necesariamente una hoja del árbol de reglas. Summary sigue buscando en los hijos cuando el grupo padre pertenece a otro campo o carece de ruta.

Las rutas se comparan exactamente: solicitar Address no devuelve por prefijo los mensajes de Address.City.

Evidencia tipada ​

La evidencia captura los datos usados en una evaluación para construir después un mensaje consistente. Evita repetir una consulta en el formateador o leer un valor mutable que ya cambió.

csharp
using Greencore.platform.validators;

var minimum = ValidationRule.WithEvidence<string, LengthEvidence>(
    "text.minimum",
    text => new(text.Length >= 3, new(3, text.Length)),
    "name.short",
    evidence => $"Se necesitan {evidence.Minimum} unidades UTF-16; se recibieron {evidence.Actual}.");

var plan = Validation.For<string>().Add(minimum).Build();
var report = plan.Validate("A");
Console.WriteLine(report.Diagnostics[0].Message);

public sealed record LengthEvidence(int Minimum, int Actual);

ConditionResult<TEvidence> enlaza por tipo el resultado y su evidencia. Existen variantes locales/contextuales y síncronas/asíncronas de las fábricas. El árbol heterogéneo almacena internamente la evidencia como object, pero el formateador tipado recibe TEvidence.

El ejemplo supone texto no nulo. Para entradas opcionales, adapta la condición o protégela con una regla de presencia. La biblioteca no clona la evidencia: entrega una instantánea estable y evita incluir entidades o servicios completos cuando solo necesitas dos valores.

Fallos de validación y fallos técnicos ​

Una condición que devuelve false genera un incumplimiento. Una consulta que lanza una excepción interrumpe el plan; no se transforma automáticamente en «correo duplicado» u otro diagnóstico funcional. Una cancelación tampoco significa que el candidato sea inválido.

Las sesiones de formulario representan estos casos mediante Failed y Canceled, conservando la excepción técnica en Error cuando corresponde. La aplicación puede decidir cómo mostrar o registrar ese problema sin presentarlo como error del campo.

Integración con otras APIs ​

RuleFailureReason adapta recursivamente un diagnóstico al modelo de razones de platform.errors, conservando código y evaluación. ValidationRunner<TContext, TFailure> atiende el contrato IValidationRule<TContext, TFailure>: una regla devuelve null al cumplir y una instancia de fallo al incumplir. El runner ejecuta secuencialmente reglas independientes y reúne todos sus fallos.

Estas APIs permiten integrar consumidores existentes sin exigirles que presenten directamente un ValidationReport.

Fuentes: diagnósticos, reporte y fábricas con evidencia.

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