< Summary

Information
Class: NexusLabs.Needlr.Injection.ServiceCollectionPopulator
Assembly: NexusLabs.Needlr.Injection
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Injection/ServiceCollectionPopulator.cs
Line coverage
95%
Covered lines: 44
Uncovered lines: 2
Coverable lines: 46
Total lines: 110
Line coverage: 95.6%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
RegisterToServiceCollection(...)100%66100%
.ctor(...)100%11100%
.ctor(...)100%11100%
get_Item(...)100%210%
get_Count()100%210%
GetEnumerator()100%11100%
System.Collections.IEnumerable.GetEnumerator()100%11100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Injection/ServiceCollectionPopulator.cs

#LineLine coverage
 1using Microsoft.Extensions.Configuration;
 2using Microsoft.Extensions.DependencyInjection;
 3
 4using System.Diagnostics.CodeAnalysis;
 5using System.Reflection;
 6
 7namespace NexusLabs.Needlr.Injection;
 8
 9/// <summary>
 10/// Default implementation of <see cref="IServiceCollectionPopulator"/> that registers discovered types into a service c
 11/// Handles type registration, plugin execution, and built-in service factory registration.
 12/// </summary>
 13[DoNotAutoRegister]
 14public sealed class ServiceCollectionPopulator : IServiceCollectionPopulator
 15{
 16    private readonly ITypeRegistrar _typeRegistrar;
 17    private readonly ITypeFilterer _typeFilterer;
 18    private readonly IPluginFactory _pluginFactory;
 19
 20    /// <summary>
 21    /// Initializes a new instance of the <see cref="ServiceCollectionPopulator"/> class.
 22    /// </summary>
 23    /// <param name="typeRegistrar">The type registrar to use for service registration.</param>
 24    /// <param name="typeFilterer">The type filterer to determine service lifetimes.</param>
 25    /// <param name="pluginFactory">The plugin factory to use for plugin discovery and instantiation.</param>
 53526    public ServiceCollectionPopulator(
 53527        ITypeRegistrar typeRegistrar,
 53528        ITypeFilterer typeFilterer,
 53529        IPluginFactory pluginFactory)
 30    {
 53531        ArgumentNullException.ThrowIfNull(typeRegistrar);
 53532        ArgumentNullException.ThrowIfNull(typeFilterer);
 53533        ArgumentNullException.ThrowIfNull(pluginFactory);
 34
 53535        _typeRegistrar = typeRegistrar;
 53536        _typeFilterer = typeFilterer;
 53537        _pluginFactory = pluginFactory;
 53538    }
 39
 40    /// <inheritdoc />
 41    public IServiceCollection RegisterToServiceCollection(
 42        IServiceCollection services,
 43        IConfiguration config,
 44        IReadOnlyList<Assembly> candidateAssemblies)
 45    {
 53546        ArgumentNullException.ThrowIfNull(services);
 53547        ArgumentNullException.ThrowIfNull(config);
 53548        ArgumentNullException.ThrowIfNull(candidateAssemblies);
 49
 53550        services.AddSingleton(services);
 53551        services.AddSingleton(provider => provider);
 53552        services.AddSingleton(typeof(Lazy<>), typeof(LazyFactory<>));
 53553        services.AddSingleton(typeof(IReadOnlyList<>), typeof(ReadOnlyListFactory<>));
 53554        services.AddSingleton(typeof(IReadOnlyCollection<>), typeof(ReadOnlyListFactory<>));
 53555        services.AddSingleton(_pluginFactory);
 56
 412657        foreach (var assembly in candidateAssemblies)
 58        {
 152859            services.AddSingleton(assembly);
 60        }
 61
 53562        _typeRegistrar.RegisterTypesFromAssemblies(
 53563            services,
 53564            _typeFilterer,
 53565            candidateAssemblies);
 66
 53567        ServiceCollectionPluginOptions options = new(
 53568            services,
 53569            config,
 53570            candidateAssemblies,
 53571            _pluginFactory);
 72
 53573        var executedPluginTypes = new HashSet<Type>();
 750074        foreach (var serviceCollectionPlugin in _pluginFactory.CreatePluginsFromAssemblies<IServiceCollectionPlugin>(can
 75        {
 321576            var pluginType = serviceCollectionPlugin.GetType();
 321577            if (!executedPluginTypes.Add(pluginType))
 78            {
 79                // Skip duplicate plugin instances of the same type
 80                continue;
 81            }
 82
 321583            serviceCollectionPlugin.Configure(options);
 84        }
 85
 53586        return services;
 87    }
 88
 89    private sealed class LazyFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConst
 2090        Lazy<T>(() => provider.GetRequiredService<T>())
 91        where T : notnull
 92    {
 93    }
 94
 3395    private sealed class ReadOnlyListFactory<T>(IServiceProvider provider) : IReadOnlyList<T>
 96        where T : notnull
 97    {
 6698        private readonly Lazy<IReadOnlyList<T>> _lazyItems = new(() => provider
 6699            .GetServices<T>()
 66100            .ToArray());
 101
 0102        public T this[int index] => _lazyItems.Value[index];
 103
 0104        public int Count => _lazyItems.Value.Count;
 105
 42106        public IEnumerator<T> GetEnumerator() => _lazyItems.Value.GetEnumerator();
 107
 4108        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 109    }
 110}