< Summary

Information
Class: Pozitron.QuerySpecification.TypeDiscovery
Assembly: Pozitron.QuerySpecification
File(s): /home/runner/work/QuerySpecification/QuerySpecification/src/QuerySpecification/Internals/TypeDiscovery.cs
Tag: 67_15587897385
Line coverage
86%
Covered lines: 80
Uncovered lines: 13
Coverable lines: 93
Total lines: 137
Line coverage: 86%
Branch coverage
100%
Covered branches: 40
Total branches: 40
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%101084.31%
GetMemoryEvaluators()100%11100%
GetEvaluators()100%11100%
GetValidators()100%11100%
GetInstancesOf()100%11100%
GetInstancesOf(...)100%303086.48%

File(s)

/home/runner/work/QuerySpecification/QuerySpecification/src/QuerySpecification/Internals/TypeDiscovery.cs

#LineLine coverage
 1using System.Diagnostics;
 2using System.Reflection;
 3
 4namespace Pozitron.QuerySpecification;
 5
 6internal static class TypeDiscovery
 7{
 38    private static readonly Lazy<Assembly[]> _loadedAssemblies = new(
 39        () =>
 310        {
 311            try
 312            {
 313                return AppDomain.CurrentDomain
 314                    .GetAssemblies()
 315                    .Where(a =>
 26116                        a.IsDynamic == false &&
 26117                        a.FullName != null &&
 26118                        !a.FullName.StartsWith("System", StringComparison.OrdinalIgnoreCase) &&
 26119                        !a.FullName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase) &&
 26120                        !a.FullName.StartsWith("netstandard", StringComparison.OrdinalIgnoreCase) &&
 26121                        !a.FullName.StartsWith("Windows", StringComparison.OrdinalIgnoreCase)
 322                    )
 323                    .ToArray();
 324            }
 025            catch (Exception ex)
 326            {
 027                Trace.TraceError("Error loading assemblies for type discovery: {0}", ex.Message);
 028                Trace.TraceError("Stack Trace: {0}", ex.StackTrace);
 029                return [];
 330            }
 331        },
 332        LazyThreadSafetyMode.ExecutionAndPublication);
 33
 334    private static readonly Lazy<bool> _isAutoDiscoveryEnabled = new(
 335        () =>
 336        {
 337            try
 338            {
 339                return _loadedAssemblies
 340                    .Value
 69341                    .Any(x => x.GetCustomAttributes().Any(attr => attr.GetType().Equals(typeof(SpecAutoDiscoveryAttribut
 342            }
 043            catch (Exception ex)
 344            {
 045                Trace.TraceError("Error checking auto discovery attribute: {0}", ex.Message);
 046                Trace.TraceError("Stack Trace: {0}", ex.StackTrace);
 047                return false;
 348            }
 349        },
 350        LazyThreadSafetyMode.ExecutionAndPublication);
 51
 352    private static readonly Lazy<List<IEvaluator>> _evaluators = new(
 253        () => GetInstancesOf<IEvaluator, DiscoveryAttribute>(),
 354        LazyThreadSafetyMode.ExecutionAndPublication);
 55
 356    private static readonly Lazy<List<IMemoryEvaluator>> _memoryEvaluators = new(
 257        () => GetInstancesOf<IMemoryEvaluator, DiscoveryAttribute>(),
 358        LazyThreadSafetyMode.ExecutionAndPublication);
 59
 360    private static readonly Lazy<List<IValidator>> _validators = new(
 261        () => GetInstancesOf<IValidator, DiscoveryAttribute>(),
 362        LazyThreadSafetyMode.ExecutionAndPublication);
 63
 64
 1965    internal static bool IsAutoDiscoveryEnabled => _isAutoDiscoveryEnabled.Value;
 466    internal static List<IMemoryEvaluator> GetMemoryEvaluators() => _memoryEvaluators.Value.ToList();
 467    internal static List<IEvaluator> GetEvaluators() => _evaluators.Value.ToList();
 468    internal static List<IValidator> GetValidators() => _validators.Value.ToList();
 69
 70    internal static List<TType> GetInstancesOf<TType, TAttribute>()
 71        where TType : class
 72        where TAttribute : DiscoveryAttribute
 673        => GetInstancesOf<TType, TAttribute>(_loadedAssemblies.Value);
 74
 75    internal static List<TType> GetInstancesOf<TType, TAttribute>(IEnumerable<Assembly> assemblies)
 76        where TType : class
 77        where TAttribute : DiscoveryAttribute
 78    {
 79        try
 80        {
 1481            var baseType = typeof(TType);
 1482            var typeInstances = new List<(TType Instance, int Order, string TypeName)>();
 83
 1484            var types = assemblies
 1485                .SelectMany(a =>
 1486                {
 8387                    try { return a.GetTypes(); } catch { return Array.Empty<Type>(); }
 8388                })
 2847789                .Where(t => t.IsClass && !t.IsAbstract && !t.ContainsGenericParameters && baseType.IsAssignableFrom(t))
 1490                .Distinct();
 91
 22292            foreach (var type in types)
 93            {
 9794                var discoveryAttr = type.GetCustomAttribute<TAttribute>();
 9795                if (discoveryAttr is not null && !discoveryAttr.Enable)
 96                    continue;
 97
 8998                TType? instance = null;
 99
 89100                if (type.GetConstructor(Type.EmptyTypes) is not null)
 101                {
 41102                    instance = (TType?)Activator.CreateInstance(type);
 103                }
 48104                else if (type.GetFields(BindingFlags.Public | BindingFlags.Static)
 32105                    .Where(f => type.IsAssignableFrom(f.FieldType))
 48106                    .FirstOrDefault() is FieldInfo instanceField)
 107                {
 32108                    instance = (TType?)instanceField.GetValue(null);
 109                }
 16110                else if (type.GetProperties(BindingFlags.Public | BindingFlags.Static)
 8111                    .Where(f => type.IsAssignableFrom(f.PropertyType))
 16112                    .FirstOrDefault() is PropertyInfo instanceProp)
 113                {
 8114                    instance = (TType?)instanceProp.GetValue(null);
 115                }
 116
 89117                if (instance is null) continue;
 118
 81119                int order = discoveryAttr?.Order ?? int.MaxValue;
 81120                typeInstances.Add((instance, order, type.Name));
 121            }
 122
 14123            return typeInstances
 81124                .OrderBy(e => e.Order)
 81125                .ThenBy(e => e.TypeName)
 81126                .Select(e => e.Instance)
 14127                .ToList();
 128        }
 0129        catch (Exception ex)
 130        {
 0131            Trace.TraceError("Error during type discovery for {0}.", typeof(TType).Name);
 0132            Trace.TraceError("Exception: {0}", ex.Message);
 0133            Trace.TraceError("Stack Trace: {0}", ex.StackTrace);
 0134            return [];
 135        }
 14136    }
 137}