< Summary

Information
Class: NexusLabs.Needlr.Maui.MauiSyringe
Assembly: NexusLabs.Needlr.Maui
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Maui/MauiSyringe.cs
Line coverage
89%
Covered lines: 25
Uncovered lines: 3
Coverable lines: 28
Total lines: 110
Line coverage: 89.2%
Branch coverage
50%
Covered branches: 5
Total branches: 10
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_BaseSyringe()100%11100%
.ctor(...)100%11100%
PopulateInto(...)50%101086.95%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Maui/MauiSyringe.cs

#LineLine coverage
 1using Microsoft.Maui.Hosting;
 2
 3using NexusLabs.Needlr.Injection;
 4
 5namespace NexusLabs.Needlr.Maui;
 6
 7/// <summary>
 8/// Provides a fluent API for populating a .NET MAUI application's service collection with
 9/// Needlr-discovered services. Wraps a <see cref="ConfiguredSyringe"/> with MAUI-specific behavior.
 10/// </summary>
 11/// <remarks>
 12/// <para>
 13/// A MAUI head project owns a single dependency-injection container created by
 14/// <c>MauiApp.CreateBuilder()</c>. <see cref="MauiSyringe"/> applies every Needlr-discovered
 15/// registration to that container's <see cref="MauiAppBuilder.Services"/>, so MAUI resolves your
 16/// <c>App</c>, pages, and view models — and every Needlr service — from one provider with no
 17/// per-type manual registration.
 18/// </para>
 19/// <para>
 20/// Obtain a <see cref="MauiSyringe"/> by calling <c>ForMaui()</c> on a configured syringe.
 21/// </para>
 22/// </remarks>
 23/// <example>
 24/// <code>
 25/// var builder = MauiApp.CreateBuilder();
 26/// builder.UseMauiApp&lt;App&gt;();
 27///
 28/// new Syringe()
 29///     .UsingSourceGen()
 30///     .ForMaui()
 31///     .PopulateInto(builder);
 32///
 33/// return builder.Build();
 34/// </code>
 35/// </example>
 36public sealed record MauiSyringe
 37{
 2738    internal ConfiguredSyringe BaseSyringe { get; init; }
 39
 40    /// <summary>
 41    /// Initializes a new instance of the <see cref="MauiSyringe"/> class.
 42    /// </summary>
 43    /// <param name="baseSyringe">The configured syringe to wrap.</param>
 44    /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="baseSyringe"/> is <see langword="null
 345    public MauiSyringe(ConfiguredSyringe baseSyringe)
 46    {
 347        System.ArgumentNullException.ThrowIfNull(baseSyringe);
 348        BaseSyringe = baseSyringe;
 349    }
 50
 51    /// <summary>
 52    /// Applies the Needlr-discovered registrations to the supplied <see cref="MauiAppBuilder"/>'s
 53    /// service collection, using <see cref="MauiAppBuilder.Configuration"/> for options binding.
 54    /// </summary>
 55    /// <remarks>
 56    /// <para>
 57    /// The builder's <see cref="MauiAppBuilder.Configuration"/> is used to bind any
 58    /// <c>[Options]</c>- and <c>[HttpClientOptions]</c>-decorated types, matching the behavior of
 59    /// the ASP.NET and host integrations. Services already present on the builder (for example MAUI's
 60    /// own registrations, or your own <c>builder.Services.Add...</c> calls) are preserved.
 61    /// </para>
 62    /// </remarks>
 63    /// <param name="builder">The MAUI application builder to populate.</param>
 64    /// <returns>The same <paramref name="builder"/> instance, to allow chaining.</returns>
 65    /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="builder"/> is <see langword="null"/>.
 66    public MauiAppBuilder PopulateInto(MauiAppBuilder builder)
 67    {
 368        System.ArgumentNullException.ThrowIfNull(builder);
 69
 370        var typeRegistrar = BaseSyringe.GetOrCreateTypeRegistrar();
 371        var typeFilterer = BaseSyringe.GetOrCreateTypeFilterer();
 372        var pluginFactory = BaseSyringe.GetOrCreatePluginFactory();
 373        var serviceCollectionPopulator = BaseSyringe.GetOrCreateServiceCollectionPopulator(typeRegistrar, typeFilterer, 
 374        var assemblyProvider = BaseSyringe.GetOrCreateAssemblyProvider();
 375        var additionalAssemblies = BaseSyringe.GetAdditionalAssemblies();
 76
 377        var serviceProviderBuilder = BaseSyringe.GetOrCreateServiceProviderBuilder(
 378            serviceCollectionPopulator,
 379            assemblyProvider,
 380            additionalAssemblies);
 81
 382        var candidateAssemblies = serviceProviderBuilder.GetCandidateAssemblies();
 83
 384        serviceCollectionPopulator.RegisterToServiceCollection(
 385            builder.Services,
 386            builder.Configuration,
 387            candidateAssemblies);
 88
 89        // User-registered post-plugin callbacks run first, then the source-generated
 90        // options/extension registrars — the same ordering ConfiguredSyringe and the ASP.NET
 91        // integration use. Without these, [Options]-decorated types bound by the generator would
 92        // never have their IConfigureOptions<T> registered.
 693        foreach (var callback in BaseSyringe.GetPostPluginRegistrationCallbacks())
 94        {
 095            callback(builder.Services);
 96        }
 97
 398        if (SourceGenRegistry.TryGetOptionsRegistrar(out var optionsRegistrar) && optionsRegistrar is not null)
 99        {
 0100            optionsRegistrar(builder.Services, builder.Configuration);
 101        }
 102
 3103        if (SourceGenRegistry.TryGetExtensionRegistrar(out var extensionRegistrar) && extensionRegistrar is not null)
 104        {
 0105            extensionRegistrar(builder.Services, builder.Configuration);
 106        }
 107
 3108        return builder;
 109    }
 110}