< Summary

Information
Class: MyNet.Observable.Behaviors.ValidationGraphVisitor
Assembly: MyNet.Observable
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Observable/Behaviors/ValidationGraphVisitor.cs
Tag: 323_28699572109
Line coverage
91%
Covered lines: 22
Uncovered lines: 2
Coverable lines: 24
Total lines: 106
Line coverage: 91.6%
Branch coverage
83%
Covered branches: 20
Total branches: 24
Branch coverage: 83.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Validate(...)100%22100%
ValidateInternal(...)62.5%9880%
TraverseChildren(...)92.85%1414100%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Observable/Behaviors/ValidationGraphVisitor.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="ValidationGraphVisitor.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections;
 9using System.Collections.Generic;
 10using MyNet.Reflection;
 11
 12namespace MyNet.Observable.Behaviors;
 13
 14/// <summary>
 15/// Provides functionality to traverse an object graph and validate objects that implement the IValidationAware interfac
 16/// </summary>
 17public static class ValidationGraphVisitor
 18{
 19    /// <summary>
 20    /// Performs a depth-first traversal of the object graph starting from the specified root object, invoking the Valid
 21    /// </summary>
 22    /// <param name="root">The root object of the graph to validate.</param>
 23    /// <returns>True if all validatable objects in the graph are valid; otherwise, false.</returns>
 24    public static bool Validate(object? root)
 25    {
 1226        if (root is null)
 327            return true;
 28
 929        var visited = new HashSet<object>(ReferenceEqualityComparer.Instance);
 30
 931        return ValidateInternal(root, visited);
 32    }
 33
 34    /// <summary>
 35    /// Performs a depth-first traversal of the object graph starting from the specified current object, invoking the Va
 36    /// </summary>
 37    /// <param name="current">The current object being validated.</param>
 38    /// <param name="visited">A set of objects that have already been visited to prevent infinite loops.</param>
 39    /// <returns>True if all validatable objects in the graph are valid; otherwise, false.</returns>
 40    private static bool ValidateInternal(object current, HashSet<object> visited)
 41    {
 2142        if (!visited.Add(current))
 343            return true;
 44
 1845        var result = true;
 46
 1847        switch (current)
 48        {
 49            case IValidationAware validation:
 950                result &= validation.Validate();
 951                break;
 052            case ObservableObject observableObject when observableObject.Behaviors.TryGet<IValidationBehavior>(out var b
 053                result &= behavior.Validate();
 54                break;
 55        }
 56
 1857        TraverseChildren(current, child => result &= ValidateInternal(child, visited));
 58
 1859        return result;
 60    }
 61
 62    /// <summary>
 63    /// Traverses the child objects of the specified current object, invoking the provided visitor action for each child
 64    /// </summary>
 65    /// <param name="current">The current object whose child objects are to be traversed.</param>
 66    /// <param name="visitor">An action to be invoked for each child object.</param>
 67    private static void TraverseChildren(object current, Action<object> visitor)
 68    {
 1869        var properties = current.GetType().GetPublicProperties();
 70
 10271        foreach (var property in properties)
 72        {
 3373            var value = property.GetValue(current);
 74
 3375            if (value is null)
 76                continue;
 77
 3078            if (property.PropertyType.IsSimple())
 79                continue;
 80
 81            switch (value)
 82            {
 83                case string:
 84                    continue;
 85
 86                case IEnumerable enumerable:
 87                    {
 3088                        foreach (var item in enumerable)
 89                        {
 390                            if (item is null)
 91                                continue;
 92
 393                            visitor(item);
 94                        }
 95
 96                        break;
 97                    }
 98
 99                default:
 9100                    visitor(value);
 101                    break;
 102            }
 103        }
 18104    }
 105}
 106