< Summary

Information
Class: NexusLabs.Needlr.Injection.Reflection.TypeFilterers.ReflectionTypeFilterer
Assembly: NexusLabs.Needlr.Injection.Reflection
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Injection.Reflection/TypeFilterers/ReflectionTypeFilterer.cs
Line coverage
100%
Covered lines: 28
Uncovered lines: 0
Coverable lines: 28
Total lines: 70
Line coverage: 100%
Branch coverage
100%
Covered branches: 34
Total branches: 34
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IsInjectableScopedType(...)100%22100%
IsInjectableTransientType(...)100%22100%
IsInjectableSingletonType(...)100%66100%
IsInjectableType(...)100%2424100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Injection.Reflection/TypeFilterers/ReflectionTypeFilterer.cs

#LineLine coverage
 1using System.Diagnostics.CodeAnalysis;
 2using System.Reflection;
 3
 4namespace NexusLabs.Needlr.Injection.Reflection.TypeFilterers;
 5
 6/// <summary>
 7/// Type filterer that uses runtime reflection to analyze constructors.
 8/// </summary>
 9/// <remarks>
 10/// This filterer is not compatible with NativeAOT or trimming. For AOT scenarios,
 11/// use GeneratedTypeFilterer from NexusLabs.Needlr.Injection.SourceGen with the Needlr source generator instead.
 12/// </remarks>
 13[RequiresUnreferencedCode("ReflectionTypeFilterer uses reflection to analyze constructors. Use GeneratedTypeFilterer for
 14public sealed class ReflectionTypeFilterer : ITypeFilterer
 15{
 16    /// <inheritdoc />
 17    public bool IsInjectableScopedType(Type type)
 19126418        => IsInjectableType(type) && type.GetCustomAttribute<ScopedAttribute>(inherit: true) is not null;
 19
 20    /// <inheritdoc />
 21    public bool IsInjectableTransientType(Type type)
 19191022        => IsInjectableType(type) && type.GetCustomAttribute<TransientAttribute>(inherit: true) is not null;
 23
 24    /// <inheritdoc />
 25    public bool IsInjectableSingletonType(Type type)
 26    {
 28899127        if (!IsInjectableType(type))
 18920228            return false;
 29
 30        // Explicit [Singleton] attribute or no lifetime attribute (default)
 9978931        var hasSingleton = type.GetCustomAttribute<SingletonAttribute>(inherit: true) is not null;
 9978932        var hasScoped = type.GetCustomAttribute<ScopedAttribute>(inherit: true) is not null;
 9978933        var hasTransient = type.GetCustomAttribute<TransientAttribute>(inherit: true) is not null;
 34
 9978935        return hasSingleton || (!hasScoped && !hasTransient);
 36    }
 37
 38    private static bool IsInjectableType(Type type)
 39    {
 67216540        if (!TypeFiltering.IsConcreteType(type))
 56156341            return false;
 42
 11060243        if (type.GetCustomAttribute<DoNotInjectAttribute>(inherit: true) is not null)
 2544            return false;
 45
 11057746        var ctors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
 33901847        foreach (var ctor in ctors)
 48        {
 11123149            var parameters = ctor.GetParameters();
 11123150            if (parameters.Length == 0)
 9553551                return true;
 52
 1569653            if (parameters.Length == 1 && parameters[0].ParameterType == type)
 2554                return false;
 55
 1567156            if (parameters.All(p =>
 3826457                !p.ParameterType.IsAssignableTo(typeof(MulticastDelegate)) &&
 3826458                !p.ParameterType.IsValueType &&
 3826459                !p.ParameterType.Equals(typeof(string)) &&
 3826460                !p.ParameterType.IsPrimitive &&
 3826461                (p.ParameterType.IsClass ||
 3826462                p.ParameterType.IsInterface)))
 63            {
 903864                return true;
 65            }
 66        }
 67
 597968        return false;
 69    }
 70}