< Summary

Information
Class: MyNet.Primitives.SmartEnumSource
Assembly: MyNet.Primitives
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Primitives/SmartEnum/SmartEnumSource.cs
Tag: 323_28699572109
Line coverage
100%
Covered lines: 19
Uncovered lines: 0
Coverable lines: 19
Total lines: 75
Line coverage: 100%
Branch coverage
100%
Covered branches: 14
Total branches: 14
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
GetAll(...)100%22100%
GetAll()100%11100%
Discover(...)100%66100%
FindSmartEnumBaseType(...)100%66100%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Primitives/SmartEnum/SmartEnumSource.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="SmartEnumSource.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.Concurrent;
 10using System.Collections.Generic;
 11using System.Linq;
 12using System.Reflection;
 13
 14#pragma warning disable IDE0130 // Namespace does not match folder structure
 15namespace MyNet.Primitives;
 16#pragma warning restore IDE0130 // Namespace does not match folder structure
 17
 18/// <summary>
 19/// Discovers all instances declared on a smart enum type.
 20/// </summary>
 21public static class SmartEnumSource
 22{
 923    private static readonly ConcurrentDictionary<Type, IReadOnlyList<ISmartEnum>> Cache = new();
 24
 25    /// <summary>
 26    /// Returns all smart enum instances for the specified type.
 27    /// </summary>
 28    /// <param name="smartEnumType">The smart enum type.</param>
 29    /// <returns>All discovered smart enum instances.</returns>
 30    public static IReadOnlyList<ISmartEnum> GetAll(Type smartEnumType)
 31    {
 3032        ArgumentNullException.ThrowIfNull(smartEnumType);
 33
 2734        return !typeof(ISmartEnum).IsAssignableFrom(smartEnumType)
 2735            ? throw new ArgumentException($"Type '{smartEnumType.FullName}' does not implement {nameof(ISmartEnum)}.", n
 2736            : Cache.GetOrAdd(smartEnumType, Discover);
 37    }
 38
 39    /// <summary>
 40    /// Returns all smart enum instances for the specified type.
 41    /// </summary>
 42    /// <typeparam name="TSmartEnum">The smart enum type.</typeparam>
 43    /// <returns>All discovered smart enum instances.</returns>
 44    public static IReadOnlyList<TSmartEnum> GetAll<TSmartEnum>()
 45        where TSmartEnum : class, ISmartEnum
 946        => [.. GetAll(typeof(TSmartEnum)).Cast<TSmartEnum>()];
 47
 48    private static IReadOnlyList<ISmartEnum> Discover(Type smartEnumType)
 49    {
 1250        var smartEnumBase = FindSmartEnumBaseType(smartEnumType);
 1251        var allProperty = smartEnumBase?.GetProperty("All", BindingFlags.Public | BindingFlags.Static | BindingFlags.Dec
 52
 1253        return allProperty?.GetValue(null) is IEnumerable values
 1254            ? [.. values.Cast<ISmartEnum>()]
 1255            : [.. smartEnumType
 1256                .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)
 1257                .Where(field => smartEnumType.IsAssignableFrom(field.FieldType))
 1258                .Select(field => field.GetValue(null))
 1259                .OfType<ISmartEnum>()];
 60    }
 61
 62    private static Type? FindSmartEnumBaseType(Type smartEnumType)
 63    {
 5464        for (var type = smartEnumType; type is not null; type = type.BaseType)
 65        {
 2466            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(SmartEnum<,>))
 67            {
 968                return type;
 69            }
 70        }
 71
 372        return null;
 73    }
 74}
 75