< 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
 50835    public ReflectionServiceProviderBuilder(
 50836        IServiceCollectionPopulator serviceCollectionPopulator,
 50837        IAssemblyProvider assemblyProvider,
 50838        IReadOnlyList<Assembly> additionalAssemblies)
 39    {
 50840        ArgumentNullException.ThrowIfNull(serviceCollectionPopulator);
 50841        ArgumentNullException.ThrowIfNull(assemblyProvider);
 50842        ArgumentNullException.ThrowIfNull(additionalAssemblies);
 43
 50844        _serviceCollectionPopulator = serviceCollectionPopulator;
 50845        _pluginFactory = new ReflectionPluginFactory();
 50846        _lazyCandidateAssemblies = new(() =>
 50847        {
 50848            var staticAssemblies = assemblyProvider.GetCandidateAssemblies();
 50849            HashSet<string> uniqueAssemblyNames = new(StringComparer.OrdinalIgnoreCase);
 50850            List<Assembly> allCandidateAssemblies = new(additionalAssemblies.Count + staticAssemblies.Count);
 50851
 214252            foreach (var assembly in staticAssemblies)
 50853            {
 56354                var name = assembly.FullName ?? assembly.GetName().Name ?? string.Empty;
 56355                if (uniqueAssemblyNames.Add(name))
 50856                {
 56357                    allCandidateAssemblies.Add(assembly);
 50858                }
 50859            }
 50860
 104461            foreach (var assembly in additionalAssemblies)
 50862            {
 1463                var name = assembly.FullName ?? assembly.GetName().Name ?? string.Empty;
 1464                if (uniqueAssemblyNames.Add(name))
 50865                {
 766                    allCandidateAssemblies.Add(assembly);
 50867                }
 50868            }
 50869
 50870            return allCandidateAssemblies.Distinct().ToArray();
 50871        });
 50872    }
 73
 74    /// <inheritdoc />
 100975    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    {
 468107        ArgumentNullException.ThrowIfNull(services);
 468108        ArgumentNullException.ThrowIfNull(config);
 468109        ArgumentNullException.ThrowIfNull(preRegistrationCallbacks);
 468110        ArgumentNullException.ThrowIfNull(postPluginRegistrationCallbacks);
 111
 468112        services.AddSingleton(config);
 113
 956114        foreach (var callback in preRegistrationCallbacks)
 115        {
 10116            callback.Invoke(services);
 117        }
 118
 468119        _serviceCollectionPopulator.RegisterToServiceCollection(
 468120            services,
 468121            config,
 468122            GetCandidateAssemblies());
 123
 2984124        foreach (var callback in postPluginRegistrationCallbacks)
 125        {
 1025126            callback.Invoke(services);
 127        }
 128
 466129        var provider = services.BuildServiceProvider();
 130
 466131        ConfigurePostBuildServiceCollectionPlugins(provider, config);
 132
 466133        return provider;
 134    }
 135
 136    /// <inheritdoc />
 137    public void ConfigurePostBuildServiceCollectionPlugins(
 138        IServiceProvider provider,
 139        IConfiguration config)
 140    {
 501141        ArgumentNullException.ThrowIfNull(provider);
 501142        ArgumentNullException.ThrowIfNull(config);
 143
 501144        var candidateAssemblies = GetCandidateAssemblies();
 501145        PostBuildServiceCollectionPluginOptions options = new(
 501146            provider,
 501147            config,
 501148            candidateAssemblies,
 501149            _pluginFactory);
 150
 1002151        foreach (var plugin in _pluginFactory.CreatePluginsFromAssemblies<IPostBuildServiceCollectionPlugin>(candidateAs
 152        {
 0153            plugin.Configure(options);
 154        }
 501155    }
 156}