< Summary

Information
Class: NexusLabs.Needlr.Injection.SourceGen.Loaders.GeneratedAssemblyProvider
Assembly: NexusLabs.Needlr.Injection.SourceGen
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Injection.SourceGen/Loaders/GeneratedAssemblyProvider.cs
Line coverage
87%
Covered lines: 48
Uncovered lines: 7
Coverable lines: 55
Total lines: 117
Line coverage: 87.2%
Branch coverage
100%
Covered branches: 8
Total branches: 8
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%210%
.ctor(...)100%6695.65%
AddAssembly()100%22100%
GetCandidateAssemblies()100%11100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Injection.SourceGen/Loaders/GeneratedAssemblyProvider.cs

#LineLine coverage
 1using System.Reflection;
 2
 3using NexusLabs.Needlr.Generators;
 4
 5namespace NexusLabs.Needlr.Injection.SourceGen.Loaders;
 6
 7/// <summary>
 8/// An assembly provider that derives assemblies from the generated TypeRegistry.
 9/// </summary>
 10/// <remarks>
 11/// <para>
 12/// When using source generation, the TypeRegistry contains all injectable types
 13/// and plugins discovered at compile time. Generated bootstraps also provide a
 14/// registry participant type so assemblies with no injectable types or plugins
 15/// remain available without runtime assembly scanning.
 16/// </para>
 17/// <para>
 18/// This provider should be used with <see cref="PluginFactories.GeneratedPluginFactory"/>
 19/// to ensure that all generated registry participants are included in plugin discovery
 20/// when runtime assembly metadata is available.
 21/// </para>
 22/// <para>
 23/// For assembly ordering, use <c>SyringeExtensions.OrderAssemblies</c> after configuring the Syringe.
 24/// </para>
 25/// </remarks>
 26[DoNotAutoRegister]
 27public sealed class GeneratedAssemblyProvider : IAssemblyProvider
 28{
 29    private readonly Lazy<IReadOnlyList<Assembly>> _lazyAssemblies;
 30
 31    /// <summary>
 32    /// Initializes a new instance of the <see cref="GeneratedAssemblyProvider"/> class.
 33    /// </summary>
 34    /// <param name="injectableTypesProvider">A function that returns the injectable types.</param>
 35    /// <param name="pluginTypesProvider">A function that returns the plugin types.</param>
 36    /// <remarks>
 37    /// This compatibility overload can derive assemblies only from injectable and plugin metadata.
 38    /// Use the three-argument overload when generated registry participant types are available.
 39    /// </remarks>
 40    public GeneratedAssemblyProvider(
 41        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypesProvider,
 42        Func<IReadOnlyList<PluginTypeInfo>> pluginTypesProvider)
 043        : this(
 044            injectableTypesProvider,
 045            pluginTypesProvider,
 046            Array.Empty<Type>())
 47    {
 048    }
 49
 50    /// <summary>
 51    /// Initializes a new instance of the <see cref="GeneratedAssemblyProvider"/> class.
 52    /// </summary>
 53    /// <param name="injectableTypesProvider">A function that returns the injectable types.</param>
 54    /// <param name="pluginTypesProvider">A function that returns the plugin types.</param>
 55    /// <param name="registryParticipantTypes">
 56    /// Generated types whose assemblies identify every TypeRegistry participant.
 57    /// </param>
 58    /// <remarks>
 59    /// Assemblies represented by injectable and plugin metadata preserve their existing order.
 60    /// Marker-only participant assemblies are appended in registration order.
 61    /// </remarks>
 33362    public GeneratedAssemblyProvider(
 33363        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypesProvider,
 33364        Func<IReadOnlyList<PluginTypeInfo>> pluginTypesProvider,
 33365        IReadOnlyList<Type> registryParticipantTypes)
 66    {
 33367        ArgumentNullException.ThrowIfNull(injectableTypesProvider);
 33368        ArgumentNullException.ThrowIfNull(pluginTypesProvider);
 33369        ArgumentNullException.ThrowIfNull(registryParticipantTypes);
 70
 33271        var registryParticipantTypeSnapshot = registryParticipantTypes.ToArray();
 33272        _lazyAssemblies = new(() =>
 33273        {
 33274            // In NativeAOT with reflection disabled, Type.Assembly can throw.
 33275            // Candidate assemblies are only a hint for reflection-based discovery.
 33276            // For source generation, the plugin/type registries already define the universe.
 33277            try
 33278            {
 32679                var assemblies = new List<Assembly>();
 32680                var seenAssemblies = new HashSet<Assembly>();
 33281
 11061082                foreach (var info in injectableTypesProvider())
 33283                {
 5497984                    AddAssembly(info.Type.Assembly);
 33285                }
 33286
 7279287                foreach (var info in pluginTypesProvider())
 33288                {
 3607089                    AddAssembly(info.PluginType.Assembly);
 33290                }
 33291
 110492                foreach (var registryParticipantType in registryParticipantTypeSnapshot)
 33293                {
 22694                    AddAssembly(registryParticipantType.Assembly);
 33295                }
 33296
 32697                return assemblies;
 33298
 33299                void AddAssembly(Assembly assembly)
 332100                {
 91275101                    if (seenAssemblies.Add(assembly))
 332102                    {
 1552103                        assemblies.Add(assembly);
 332104                    }
 91275105                }
 332106            }
 0107            catch (NotSupportedException)
 332108            {
 0109                return Array.Empty<Assembly>();
 332110            }
 658111        });
 332112    }
 113
 114    /// <inheritdoc />
 115    public IReadOnlyList<Assembly> GetCandidateAssemblies() =>
 630116        _lazyAssemblies.Value;
 117}