< Summary

Information
Class: NexusLabs.Needlr.Injection.Reflection.ReflectionServiceProviderBuilder
Assembly: NexusLabs.Needlr.Injection.Reflection
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Injection.Reflection/ReflectionServiceProviderBuilder.cs
Line coverage
92%
Covered lines: 71
Uncovered lines: 6
Coverable lines: 77
Total lines: 156
Line coverage: 92.2%
Branch coverage
77%
Covered branches: 17
Total branches: 22
Branch coverage: 77.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
.ctor(...)75%1616100%
GetCandidateAssemblies()100%11100%
Build(...)100%11100%
Build(...)100%11100%
Build(...)100%11100%
Build(...)100%44100%
ConfigurePostBuildServiceCollectionPlugins(...)50%2290.9%

File(s)

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

#LineLine coverage
 1using Microsoft.Extensions.Configuration;
 2using Microsoft.Extensions.DependencyInjection;
 3
 4using NexusLabs.Needlr.Injection.Reflection.PluginFactories;
 5
 6using System.Diagnostics.CodeAnalysis;
 7using System.Reflection;
 8
 9namespace NexusLabs.Needlr.Injection.Reflection;
 10
 11/// <summary>
 12/// Builds and configures an <see cref="IServiceCollection"/> using reflection-based plugin discovery.
 13/// </summary>
 14/// <remarks>
 15/// This builder uses <see cref="ReflectionPluginFactory"/> for plugin discovery and is not AOT compatible.
 16/// </remarks>
 17[DoNotAutoRegister]
 18[RequiresUnreferencedCode("ReflectionServiceProviderBuilder uses reflection for plugin discovery.")]
 19public sealed class ReflectionServiceProviderBuilder : IServiceProviderBuilder
 20{
 21    private readonly IServiceCollectionPopulator _serviceCollectionPopulator;
 22    private readonly Lazy<IReadOnlyList<Assembly>> _lazyCandidateAssemblies;
 23    private readonly ReflectionPluginFactory _pluginFactory;
 24
 25    public ReflectionServiceProviderBuilder(
 26        IServiceCollectionPopulator serviceCollectionPopulator,
 27        IAssemblyProvider assemblyProvider) :
 028        this(
 029            serviceCollectionPopulator,
 030            assemblyProvider,
 031            additionalAssemblies: [])
 32    {
 033    }
 34
 52535    public ReflectionServiceProviderBuilder(
 52536        IServiceCollectionPopulator serviceCollectionPopulator,
 52537        IAssemblyProvider assemblyProvider,
 52538        IReadOnlyList<Assembly> additionalAssemblies)
 39    {
 52540        ArgumentNullException.ThrowIfNull(serviceCollectionPopulator);
 52541        ArgumentNullException.ThrowIfNull(assemblyProvider);
 52542        ArgumentNullException.ThrowIfNull(additionalAssemblies);
 43
 52544        _serviceCollectionPopulator = serviceCollectionPopulator;
 52545        _pluginFactory = new ReflectionPluginFactory();
 52546        _lazyCandidateAssemblies = new(() =>
 52547        {
 52548            var staticAssemblies = assemblyProvider.GetCandidateAssemblies();
 52549            HashSet<string> uniqueAssemblyNames = new(StringComparer.OrdinalIgnoreCase);
 52550            List<Assembly> allCandidateAssemblies = new(additionalAssemblies.Count + staticAssemblies.Count);
 52551
 221052            foreach (var assembly in staticAssemblies)
 52553            {
 58054                var name = assembly.FullName ?? assembly.GetName().Name ?? string.Empty;
 58055                if (uniqueAssemblyNames.Add(name))
 52556                {
 58057                    allCandidateAssemblies.Add(assembly);
 52558                }
 52559            }
 52560
 107861            foreach (var assembly in additionalAssemblies)
 52562            {
 1463                var name = assembly.FullName ?? assembly.GetName().Name ?? string.Empty;
 1464                if (uniqueAssemblyNames.Add(name))
 52565                {
 766                    allCandidateAssemblies.Add(assembly);
 52567                }
 52568            }
 52569
 52570            return allCandidateAssemblies.Distinct().ToArray();
 52571        });
 52572    }
 73
 74    /// <inheritdoc />
 104375    public IReadOnlyList<Assembly> GetCandidateAssemblies() => _lazyCandidateAssemblies.Value;
 76
 77    /// <inheritdoc />
 78    public IServiceProvider Build(
 79        IConfiguration config) =>
 180        Build(
 181            services: new ServiceCollection(),
 182            config: config);
 83
 84    /// <inheritdoc />
 85    public IServiceProvider Build(
 86        IServiceCollection services,
 87        IConfiguration config) =>
 188        Build(
 189            services: services,
 190            config: config,
 191            postPluginRegistrationCallbacks: []);
 92
 93    /// <inheritdoc/>
 94    public IServiceProvider Build(
 95        IServiceCollection services,
 96        IConfiguration config,
 97        IReadOnlyList<Action<IServiceCollection>> postPluginRegistrationCallbacks) =>
 198        Build(services, config, [], postPluginRegistrationCallbacks);
 99
 100    /// <inheritdoc/>
 101    public IServiceProvider Build(
 102        IServiceCollection services,
 103        IConfiguration config,
 104        IReadOnlyList<Action<IServiceCollection>> preRegistrationCallbacks,
 105        IReadOnlyList<Action<IServiceCollection>> postPluginRegistrationCallbacks)
 106    {
 485107        ArgumentNullException.ThrowIfNull(services);
 485108        ArgumentNullException.ThrowIfNull(config);
 485109        ArgumentNullException.ThrowIfNull(preRegistrationCallbacks);
 485110        ArgumentNullException.ThrowIfNull(postPluginRegistrationCallbacks);
 111
 485112        services.AddSingleton(config);
 113
 992114        foreach (var callback in preRegistrationCallbacks)
 115        {
 11116            callback.Invoke(services);
 117        }
 118
 485119        _serviceCollectionPopulator.RegisterToServiceCollection(
 485120            services,
 485121            config,
 485122            GetCandidateAssemblies());
 123
 3082124        foreach (var callback in postPluginRegistrationCallbacks)
 125        {
 1057126            callback.Invoke(services);
 127        }
 128
 483129        var provider = services.BuildServiceProvider();
 130
 483131        ConfigurePostBuildServiceCollectionPlugins(provider, config);
 132
 483133        return provider;
 134    }
 135
 136    /// <inheritdoc />
 137    public void ConfigurePostBuildServiceCollectionPlugins(
 138        IServiceProvider provider,
 139        IConfiguration config)
 140    {
 518141        ArgumentNullException.ThrowIfNull(provider);
 518142        ArgumentNullException.ThrowIfNull(config);
 143
 518144        var candidateAssemblies = GetCandidateAssemblies();
 518145        PostBuildServiceCollectionPluginOptions options = new(
 518146            provider,
 518147            config,
 518148            candidateAssemblies,
 518149            _pluginFactory);
 150
 1036151        foreach (var plugin in _pluginFactory.CreatePluginsFromAssemblies<IPostBuildServiceCollectionPlugin>(candidateAs
 152        {
 0153            plugin.Configure(options);
 154        }
 518155    }
 156}