< 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
90%
Covered lines: 70
Uncovered lines: 7
Coverable lines: 77
Total lines: 156
Line coverage: 90.9%
Branch coverage
72%
Covered branches: 16
Total branches: 22
Branch coverage: 72.7%
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(...)68.75%161697.22%
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
 28835    public ReflectionServiceProviderBuilder(
 28836        IServiceCollectionPopulator serviceCollectionPopulator,
 28837        IAssemblyProvider assemblyProvider,
 28838        IReadOnlyList<Assembly> additionalAssemblies)
 39    {
 28840        ArgumentNullException.ThrowIfNull(serviceCollectionPopulator);
 28841        ArgumentNullException.ThrowIfNull(assemblyProvider);
 28842        ArgumentNullException.ThrowIfNull(additionalAssemblies);
 43
 28844        _serviceCollectionPopulator = serviceCollectionPopulator;
 28845        _pluginFactory = new ReflectionPluginFactory();
 28846        _lazyCandidateAssemblies = new(() =>
 28847        {
 28848            var staticAssemblies = assemblyProvider.GetCandidateAssemblies();
 28849            HashSet<string> uniqueAssemblyNames = new(StringComparer.OrdinalIgnoreCase);
 28850            List<Assembly> allCandidateAssemblies = new(additionalAssemblies.Count + staticAssemblies.Count);
 28851
 126052            foreach (var assembly in staticAssemblies)
 28853            {
 34254                var name = assembly.FullName ?? assembly.GetName().Name ?? string.Empty;
 34255                if (uniqueAssemblyNames.Add(name))
 28856                {
 34257                    allCandidateAssemblies.Add(assembly);
 28858                }
 28859            }
 28860
 59061            foreach (var assembly in additionalAssemblies)
 28862            {
 763                var name = assembly.FullName ?? assembly.GetName().Name ?? string.Empty;
 764                if (uniqueAssemblyNames.Add(name))
 28865                {
 066                    allCandidateAssemblies.Add(assembly);
 28867                }
 28868            }
 28869
 28870            return allCandidateAssemblies.Distinct().ToArray();
 28871        });
 28872    }
 73
 74    /// <inheritdoc />
 56975    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    {
 248107        ArgumentNullException.ThrowIfNull(services);
 248108        ArgumentNullException.ThrowIfNull(config);
 248109        ArgumentNullException.ThrowIfNull(preRegistrationCallbacks);
 248110        ArgumentNullException.ThrowIfNull(postPluginRegistrationCallbacks);
 111
 248112        services.AddSingleton(config);
 113
 514114        foreach (var callback in preRegistrationCallbacks)
 115        {
 9116            callback.Invoke(services);
 117        }
 118
 248119        _serviceCollectionPopulator.RegisterToServiceCollection(
 248120            services,
 248121            config,
 248122            GetCandidateAssemblies());
 123
 1604124        foreach (var callback in postPluginRegistrationCallbacks)
 125        {
 555126            callback.Invoke(services);
 127        }
 128
 246129        var provider = services.BuildServiceProvider();
 130
 246131        ConfigurePostBuildServiceCollectionPlugins(provider, config);
 132
 246133        return provider;
 134    }
 135
 136    /// <inheritdoc />
 137    public void ConfigurePostBuildServiceCollectionPlugins(
 138        IServiceProvider provider,
 139        IConfiguration config)
 140    {
 281141        ArgumentNullException.ThrowIfNull(provider);
 281142        ArgumentNullException.ThrowIfNull(config);
 143
 281144        var candidateAssemblies = GetCandidateAssemblies();
 281145        PostBuildServiceCollectionPluginOptions options = new(
 281146            provider,
 281147            config,
 281148            candidateAssemblies,
 281149            _pluginFactory);
 150
 562151        foreach (var plugin in _pluginFactory.CreatePluginsFromAssemblies<IPostBuildServiceCollectionPlugin>(candidateAs
 152        {
 0153            plugin.Configure(options);
 154        }
 281155    }
 156}