< Summary

Information
Class: NexusLabs.Needlr.Generators.NeedlrSourceGenBootstrap
Assembly: NexusLabs.Needlr.Generators.Attributes
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Generators.Attributes/NeedlrSourceGenBootstrap.cs
Line coverage
100%
Covered lines: 192
Uncovered lines: 0
Coverable lines: 192
Total lines: 613
Line coverage: 100%
Branch coverage
94%
Covered branches: 53
Total branches: 56
Branch coverage: 94.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%22100%
get_InjectableTypeProvider()100%11100%
get_PluginTypeProvider()100%11100%
get_RegistryParticipantTypes()100%11100%
get_DecoratorApplier()100%11100%
get_OptionsRegistrar()100%11100%
.cctor()100%11100%
RegisterPlugins(...)100%22100%
Register(...)100%11100%
Register(...)100%11100%
Register(...)100%11100%
Register(...)100%11100%
Register(...)100%22100%
RegisterCore(...)83.33%66100%
RegisterExtension(...)100%22100%
TryGetProviders(...)100%11100%
TryGetProviders(...)100%66100%
TryGetDecoratorApplier(...)100%66100%
TryGetOptionsRegistrar(...)100%66100%
TryGetExtensionRegistrar(...)100%44100%
ClearRegistrationsForTesting()100%11100%
BeginTestScope(...)100%11100%
BeginTestScope(...)83.33%66100%
.ctor(...)100%11100%
Dispose()100%11100%
Combine(...)100%1414100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Generators.Attributes/NeedlrSourceGenBootstrap.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading;
 5
 6namespace NexusLabs.Needlr.Generators;
 7
 8/// <summary>
 9/// Runtime bootstrap registry for source-generated Needlr components.
 10/// </summary>
 11/// <remarks>
 12/// The source generator emits a module initializer in the host assembly that calls
 13/// one of the Register overloads with the generated TypeRegistry identity and providers.
 14/// Needlr runtime can then discover generated registries without any runtime reflection.
 15/// </remarks>
 16public static class NeedlrSourceGenBootstrap
 17{
 18    private sealed class Registration
 19    {
 27520        public Registration(
 27521            Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 27522            Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider,
 27523            IReadOnlyList<Type>? registryParticipantTypes = null,
 27524            Action<object>? decoratorApplier = null,
 27525            Action<object, object>? optionsRegistrar = null)
 26        {
 27527            InjectableTypeProvider = injectableTypeProvider;
 27528            PluginTypeProvider = pluginTypeProvider;
 27529            RegistryParticipantTypes = registryParticipantTypes is null
 27530                ? Array.Empty<Type>()
 27531                : registryParticipantTypes.ToArray();
 27532            DecoratorApplier = decoratorApplier;
 27533            OptionsRegistrar = optionsRegistrar;
 27534        }
 35
 243336        public Func<IReadOnlyList<InjectableTypeInfo>> InjectableTypeProvider { get; }
 243337        public Func<IReadOnlyList<PluginTypeInfo>> PluginTypeProvider { get; }
 243338        public IReadOnlyList<Type> RegistryParticipantTypes { get; }
 248339        public Action<object>? DecoratorApplier { get; }
 214440        public Action<object, object>? OptionsRegistrar { get; }
 41    }
 42
 2943    private static readonly object _gate = new object();
 2944    private static readonly List<Registration> _registrations = new List<Registration>();
 2945    private static readonly List<Action<object, object>> _extensionRegistrars = new List<Action<object, object>>();
 46
 2947    private static readonly AsyncLocal<Registration?> _asyncLocalOverride = new AsyncLocal<Registration?>();
 48
 49    private static Registration? _cachedCombined;
 50
 51    /// <summary>
 52    /// Registers plugin types that were emitted by another source generator and are therefore
 53    /// invisible to <c>TypeRegistryGenerator</c> at compile time.
 54    /// </summary>
 55    /// <param name="pluginTypeProvider">Provider for the generator-emitted plugin types.</param>
 56    /// <remarks>
 57    /// <para>
 58    /// Roslyn source generators run in isolation — each generator receives the original
 59    /// compilation and cannot see types emitted by other generators. This means
 60    /// <c>TypeRegistryGenerator</c> cannot discover types produced by a second generator
 61    /// (e.g., a <c>CacheProviderGenerator</c> emitting <c>*CacheConfiguration</c> records).
 62    /// </para>
 63    /// <para>
 64    /// The solution is a runtime registration: the second generator emits a
 65    /// <c>[ModuleInitializer]</c> that calls <c>RegisterPlugins()</c>. Module initializers run
 66    /// before any user code, so by the time the application calls
 67    /// <c>IPluginFactory.CreatePluginsFromAssemblies&lt;T&gt;()</c> all providers are combined.
 68    /// </para>
 69    /// <para>
 70    /// Example of what the second generator should emit:
 71    /// <code>
 72    /// [ModuleInitializer]
 73    /// internal static void Initialize()
 74    /// {
 75    ///     NeedlrSourceGenBootstrap.RegisterPlugins(() =>
 76    ///     [
 77    ///         new PluginTypeInfo(
 78    ///             typeof(MyCacheConfiguration),
 79    ///             [typeof(CacheConfiguration)],
 80    ///             static () => new MyCacheConfiguration(),
 81    ///             [])
 82    ///     ]);
 83    /// }
 84    /// </code>
 85    /// </para>
 86    /// </remarks>
 87    public static void RegisterPlugins(Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider)
 88    {
 1689        if (pluginTypeProvider is null) throw new ArgumentNullException(nameof(pluginTypeProvider));
 3890        Register(() => Array.Empty<InjectableTypeInfo>(), pluginTypeProvider);
 1491    }
 92
 93    /// <summary>
 94    /// Registers the generated type and plugin providers for this application.
 95    /// </summary>
 96    public static void Register(
 97        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 98        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider)
 99    {
 91100        Register(injectableTypeProvider, pluginTypeProvider, (Action<object>?)null);
 89101    }
 102
 103    /// <summary>
 104    /// Registers the generated type, plugin, and decorator providers for this application.
 105    /// </summary>
 106    /// <param name="injectableTypeProvider">Provider for injectable types.</param>
 107    /// <param name="pluginTypeProvider">Provider for plugin types.</param>
 108    /// <param name="decoratorApplier">
 109    /// Action that applies decorators to the service collection.
 110    /// The parameter is an IServiceCollection, but typed as object to avoid dependency on Microsoft.Extensions.Dependen
 111    /// </param>
 112    public static void Register(
 113        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 114        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider,
 115        Action<object>? decoratorApplier)
 116    {
 96117        Register(injectableTypeProvider, pluginTypeProvider, decoratorApplier, null);
 94118    }
 119
 120    /// <summary>
 121    /// Registers the generated type, plugin, decorator, and options providers for this application.
 122    /// </summary>
 123    /// <param name="injectableTypeProvider">Provider for injectable types.</param>
 124    /// <param name="pluginTypeProvider">Provider for plugin types.</param>
 125    /// <param name="decoratorApplier">
 126    /// Action that applies decorators to the service collection.
 127    /// The parameter is an IServiceCollection, but typed as object to avoid dependency on Microsoft.Extensions.Dependen
 128    /// </param>
 129    /// <param name="optionsRegistrar">
 130    /// Action that registers options with the service collection and configuration.
 131    /// Parameters are (IServiceCollection, IConfiguration), typed as object to avoid dependencies.
 132    /// </param>
 133    public static void Register(
 134        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 135        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider,
 136        Action<object>? decoratorApplier,
 137        Action<object, object>? optionsRegistrar)
 138    {
 101139        RegisterCore(
 101140            injectableTypeProvider,
 101141            pluginTypeProvider,
 101142            Array.Empty<Type>(),
 101143            decoratorApplier,
 101144            optionsRegistrar);
 99145    }
 146
 147    /// <summary>
 148    /// Registers the generated registry identity and its type and plugin providers.
 149    /// </summary>
 150    /// <param name="registryParticipantType">
 151    /// A generated type whose assembly identifies the registry participant.
 152    /// </param>
 153    /// <param name="injectableTypeProvider">Provider for injectable types.</param>
 154    /// <param name="pluginTypeProvider">Provider for plugin types.</param>
 155    /// <remarks>
 156    /// The generated <c>TypeRegistry</c> type is carried separately from injectable and plugin
 157    /// metadata so assemblies with empty registries remain visible to Needlr plugins.
 158    /// </remarks>
 159    /// <example>
 160    /// <code>
 161    /// NeedlrSourceGenBootstrap.Register(
 162    ///     typeof(MyApp.Generated.TypeRegistry),
 163    ///     MyApp.Generated.TypeRegistry.GetInjectableTypes,
 164    ///     MyApp.Generated.TypeRegistry.GetPluginTypes);
 165    /// </code>
 166    /// </example>
 167    public static void Register(
 168        Type registryParticipantType,
 169        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 170        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider)
 171    {
 10172        Register(
 10173            registryParticipantType,
 10174            injectableTypeProvider,
 10175            pluginTypeProvider,
 10176            null,
 10177            null);
 9178    }
 179
 180    /// <summary>
 181    /// Registers the generated registry identity and its type, plugin, decorator, and options providers.
 182    /// </summary>
 183    /// <param name="registryParticipantType">
 184    /// A generated type whose assembly identifies the registry participant.
 185    /// </param>
 186    /// <param name="injectableTypeProvider">Provider for injectable types.</param>
 187    /// <param name="pluginTypeProvider">Provider for plugin types.</param>
 188    /// <param name="decoratorApplier">
 189    /// Action that applies decorators to the service collection.
 190    /// The parameter is an IServiceCollection, but typed as object to avoid dependency on Microsoft.Extensions.Dependen
 191    /// </param>
 192    /// <param name="optionsRegistrar">
 193    /// Action that registers options with the service collection and configuration.
 194    /// Parameters are (IServiceCollection, IConfiguration), typed as object to avoid dependencies.
 195    /// </param>
 196    /// <remarks>
 197    /// Generated module initializers use this overload so the runtime can retain assembly identity
 198    /// even when both metadata providers return empty collections.
 199    /// </remarks>
 200    /// <example>
 201    /// <code>
 202    /// NeedlrSourceGenBootstrap.Register(
 203    ///     typeof(MyApp.Generated.TypeRegistry),
 204    ///     MyApp.Generated.TypeRegistry.GetInjectableTypes,
 205    ///     MyApp.Generated.TypeRegistry.GetPluginTypes,
 206    ///     null,
 207    ///     null);
 208    /// </code>
 209    /// </example>
 210    public static void Register(
 211        Type registryParticipantType,
 212        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 213        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider,
 214        Action<object>? decoratorApplier,
 215        Action<object, object>? optionsRegistrar)
 216    {
 68217        if (registryParticipantType is null) throw new ArgumentNullException(nameof(registryParticipantType));
 218
 66219        RegisterCore(
 66220            injectableTypeProvider,
 66221            pluginTypeProvider,
 66222            new[] { registryParticipantType },
 66223            decoratorApplier,
 66224            optionsRegistrar);
 66225    }
 226
 227    private static void RegisterCore(
 228        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 229        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider,
 230        IReadOnlyList<Type> registryParticipantTypes,
 231        Action<object>? decoratorApplier,
 232        Action<object, object>? optionsRegistrar)
 233    {
 168234        if (injectableTypeProvider is null) throw new ArgumentNullException(nameof(injectableTypeProvider));
 167235        if (pluginTypeProvider is null) throw new ArgumentNullException(nameof(pluginTypeProvider));
 165236        if (registryParticipantTypes is null) throw new ArgumentNullException(nameof(registryParticipantTypes));
 237
 165238        lock (_gate)
 239        {
 165240            _registrations.Add(new Registration(
 165241                injectableTypeProvider,
 165242                pluginTypeProvider,
 165243                registryParticipantTypes,
 165244                decoratorApplier,
 165245                optionsRegistrar));
 165246            _cachedCombined = null;
 165247        }
 165248    }
 249
 250    /// <summary>
 251    /// Registers an extension that provides additional service registrations.
 252    /// Extensions are invoked after the main options registrar during BuildServiceProvider.
 253    /// </summary>
 254    /// <param name="extensionRegistrar">
 255    /// Action that registers extension services with the service collection and configuration.
 256    /// Parameters are (IServiceCollection, IConfiguration), typed as object to avoid dependencies.
 257    /// </param>
 258    /// <remarks>
 259    /// <para>
 260    /// Use this method from extension package module initializers to register additional services.
 261    /// For example, FluentValidation can register its validators without modifying core Needlr.
 262    /// </para>
 263    /// <para>
 264    /// Needlr's own runtime composition (<c>ConfiguredSyringe</c>, <c>WebApplicationSyringe</c>,
 265    /// and <c>MauiSyringe</c>) reads options and extension registrars from
 266    /// <c>NexusLabs.Needlr.SourceGenRegistry</c> so that <c>NexusLabs.Needlr.Injection</c> does not
 267    /// need a dependency on this assembly. Extension packages that already depend on
 268    /// <c>NexusLabs.Needlr.Generators.Attributes</c> may keep using this registry; extension
 269    /// packages that only depend on <c>NexusLabs.Needlr</c> should use
 270    /// <c>SourceGenRegistry.RegisterExtension</c> instead.
 271    /// </para>
 272    /// </remarks>
 273    public static void RegisterExtension(Action<object, object> extensionRegistrar)
 274    {
 11275        if (extensionRegistrar is null) throw new ArgumentNullException(nameof(extensionRegistrar));
 276
 9277        lock (_gate)
 278        {
 9279            _extensionRegistrars.Add(extensionRegistrar);
 9280            _cachedCombined = null;
 9281        }
 9282    }
 283
 284    /// <summary>
 285    /// Gets the registered providers (if any).
 286    /// </summary>
 287    public static bool TryGetProviders(
 288        out Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 289        out Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider)
 290    {
 93291        return TryGetProviders(
 93292            out injectableTypeProvider,
 93293            out pluginTypeProvider,
 93294            out _);
 295    }
 296
 297    /// <summary>
 298    /// Gets the registered providers and generated registry participant types, if any.
 299    /// </summary>
 300    /// <param name="injectableTypeProvider">The combined injectable type provider.</param>
 301    /// <param name="pluginTypeProvider">The combined plugin type provider.</param>
 302    /// <param name="registryParticipantTypes">
 303    /// Generated types whose assemblies identify every registered TypeRegistry participant.
 304    /// </param>
 305    /// <returns>
 306    /// <see langword="true"/> when at least one source-generated registration exists; otherwise,
 307    /// <see langword="false"/>.
 308    /// </returns>
 309    /// <remarks>
 310    /// Participant types are returned in registration order and deduplicated by type. Consumers
 311    /// can derive assembly identity from them without scanning the current <c>AppDomain</c>.
 312    /// </remarks>
 313    /// <example>
 314    /// <code>
 315    /// if (NeedlrSourceGenBootstrap.TryGetProviders(
 316    ///     out var injectableTypes,
 317    ///     out var pluginTypes,
 318    ///     out var registryParticipants))
 319    /// {
 320    ///     // Configure the source-generated runtime from the returned metadata.
 321    /// }
 322    /// </code>
 323    /// </example>
 324    public static bool TryGetProviders(
 325        out Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 326        out Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider,
 327        out IReadOnlyList<Type> registryParticipantTypes)
 328    {
 306329        var local = _asyncLocalOverride.Value;
 306330        if (local is not null)
 331        {
 14332            injectableTypeProvider = local.InjectableTypeProvider;
 14333            pluginTypeProvider = local.PluginTypeProvider;
 14334            registryParticipantTypes = local.RegistryParticipantTypes;
 14335            return true;
 336        }
 337
 292338        lock (_gate)
 339        {
 292340            if (_registrations.Count == 0)
 341            {
 8342                injectableTypeProvider = null!;
 8343                pluginTypeProvider = null!;
 8344                registryParticipantTypes = null!;
 8345                return false;
 346            }
 347
 284348            if (_cachedCombined is null)
 349            {
 86350                _cachedCombined = Combine(_registrations);
 351            }
 352
 284353            injectableTypeProvider = _cachedCombined.InjectableTypeProvider;
 284354            pluginTypeProvider = _cachedCombined.PluginTypeProvider;
 284355            registryParticipantTypes = _cachedCombined.RegistryParticipantTypes;
 284356            return true;
 357        }
 292358    }
 359
 360    /// <summary>
 361    /// Gets the decorator applier (if any).
 362    /// </summary>
 363    /// <param name="decoratorApplier">
 364    /// Action that applies decorators to the service collection.
 365    /// The parameter is an IServiceCollection, but typed as object to avoid dependency on Microsoft.Extensions.Dependen
 366    /// </param>
 367    /// <returns>True if a decorator applier is registered.</returns>
 368    public static bool TryGetDecoratorApplier(out Action<object>? decoratorApplier)
 369    {
 331370        var local = _asyncLocalOverride.Value;
 331371        if (local is not null)
 372        {
 2373            decoratorApplier = local.DecoratorApplier;
 2374            return decoratorApplier is not null;
 375        }
 376
 329377        lock (_gate)
 378        {
 329379            if (_registrations.Count == 0)
 380            {
 8381                decoratorApplier = null;
 8382                return false;
 383            }
 384
 321385            if (_cachedCombined is null)
 386            {
 4387                _cachedCombined = Combine(_registrations);
 388            }
 389
 321390            decoratorApplier = _cachedCombined.DecoratorApplier;
 321391            return decoratorApplier is not null;
 392        }
 329393    }
 394
 395    /// <summary>
 396    /// Gets the options registrar (if any).
 397    /// </summary>
 398    /// <param name="optionsRegistrar">
 399    /// Action that registers options with the service collection and configuration.
 400    /// Parameters are (IServiceCollection, IConfiguration), typed as object to avoid dependencies.
 401    /// </param>
 402    /// <returns>True if an options registrar is registered.</returns>
 403    /// <remarks>
 404    /// The options registrar is supplied by the generated module initializer through the
 405    /// four-argument <see cref="Register(Func{IReadOnlyList{InjectableTypeInfo}}, Func{IReadOnlyList{PluginTypeInfo}}, 
 406    /// overload. Needlr's own runtime composition reads options registrars from
 407    /// <c>NexusLabs.Needlr.SourceGenRegistry</c>; this accessor exists for hosts that compose
 408    /// generated registrations directly against this assembly.
 409    /// </remarks>
 410    public static bool TryGetOptionsRegistrar(out Action<object, object>? optionsRegistrar)
 411    {
 6412        var local = _asyncLocalOverride.Value;
 6413        if (local is not null)
 414        {
 1415            optionsRegistrar = local.OptionsRegistrar;
 1416            return optionsRegistrar is not null;
 417        }
 418
 5419        lock (_gate)
 420        {
 5421            if (_registrations.Count == 0)
 422            {
 2423                optionsRegistrar = null;
 2424                return false;
 425            }
 426
 3427            if (_cachedCombined is null)
 428            {
 3429                _cachedCombined = Combine(_registrations);
 430            }
 431
 3432            optionsRegistrar = _cachedCombined.OptionsRegistrar;
 3433            return optionsRegistrar is not null;
 434        }
 5435    }
 436
 437    /// <summary>
 438    /// Gets the combined extension registrar (if any extensions are registered).
 439    /// </summary>
 440    /// <param name="extensionRegistrar">
 441    /// Combined action that invokes all registered extensions.
 442    /// Parameters are (IServiceCollection, IConfiguration), typed as object to avoid dependencies.
 443    /// </param>
 444    /// <returns>True if any extension registrars are registered.</returns>
 445    /// <remarks>
 446    /// The returned action invokes every registrar in registration order. Unlike
 447    /// <c>TryGetProviders</c>, extension registrars are not affected by test scopes.
 448    /// </remarks>
 449    public static bool TryGetExtensionRegistrar(out Action<object, object>? extensionRegistrar)
 450    {
 7451        lock (_gate)
 452        {
 7453            if (_extensionRegistrars.Count == 0)
 454            {
 2455                extensionRegistrar = null;
 2456                return false;
 457            }
 458
 5459            var registrars = _extensionRegistrars.ToArray();
 5460            extensionRegistrar = (services, config) =>
 5461            {
 20462                foreach (var registrar in registrars)
 5463                {
 6464                    registrar(services, config);
 5465                }
 9466            };
 5467            return true;
 468        }
 7469    }
 470
 471    /// <summary>
 472    /// Clears every global registration, including extension registrars and the cached
 473    /// combined registration. For testing purposes only.
 474    /// </summary>
 475    internal static void ClearRegistrationsForTesting()
 476    {
 102477        lock (_gate)
 478        {
 102479            _registrations.Clear();
 102480            _extensionRegistrars.Clear();
 102481            _cachedCombined = null;
 102482        }
 102483    }
 484
 485    internal static IDisposable BeginTestScope(
 486        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 487        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider)
 488    {
 18489        return BeginTestScope(
 18490            injectableTypeProvider,
 18491            pluginTypeProvider,
 18492            Array.Empty<Type>());
 493    }
 494
 495    internal static IDisposable BeginTestScope(
 496        Func<IReadOnlyList<InjectableTypeInfo>> injectableTypeProvider,
 497        Func<IReadOnlyList<PluginTypeInfo>> pluginTypeProvider,
 498        IReadOnlyList<Type> registryParticipantTypes)
 499    {
 20500        if (injectableTypeProvider is null) throw new ArgumentNullException(nameof(injectableTypeProvider));
 19501        if (pluginTypeProvider is null) throw new ArgumentNullException(nameof(pluginTypeProvider));
 17502        if (registryParticipantTypes is null) throw new ArgumentNullException(nameof(registryParticipantTypes));
 503
 17504        var prior = _asyncLocalOverride.Value;
 17505        _asyncLocalOverride.Value = new Registration(
 17506            injectableTypeProvider,
 17507            pluginTypeProvider,
 17508            registryParticipantTypes);
 17509        return new Scope(prior);
 510    }
 511
 512    private sealed class Scope : IDisposable
 513    {
 514        private readonly Registration? _prior;
 515
 17516        public Scope(Registration? prior)
 517        {
 17518            _prior = prior;
 17519        }
 520
 521        public void Dispose()
 522        {
 17523            _asyncLocalOverride.Value = _prior;
 17524        }
 525    }
 526
 527    private static Registration Combine(IReadOnlyList<Registration> registrations)
 528    {
 529        // Snapshot the current registrations to avoid capturing a mutable List.
 2228530        var injectableProviders = registrations.Select(r => r.InjectableTypeProvider).ToArray();
 2228531        var pluginProviders = registrations.Select(r => r.PluginTypeProvider).ToArray();
 2253532        var decoratorAppliers = registrations.Where(r => r.DecoratorApplier is not null).Select(r => r.DecoratorApplier!
 2233533        var optionsRegistrars = registrations.Where(r => r.OptionsRegistrar is not null).Select(r => r.OptionsRegistrar!
 93534        var registryParticipantTypes = new List<Type>();
 93535        var seenRegistryParticipantTypes = new HashSet<Type>();
 536
 4456537        foreach (var registration in registrations)
 538        {
 4320539            foreach (var registryParticipantType in registration.RegistryParticipantTypes)
 540            {
 25541                if (seenRegistryParticipantTypes.Add(registryParticipantType))
 542                {
 24543                    registryParticipantTypes.Add(registryParticipantType);
 544                }
 545            }
 546        }
 547
 548        IReadOnlyList<InjectableTypeInfo> GetInjectableTypes()
 549        {
 550            var result = new List<InjectableTypeInfo>();
 551            var seen = new HashSet<Type>();
 552
 553            foreach (var provider in injectableProviders)
 554            {
 555                foreach (var info in provider())
 556                {
 557                    if (seen.Add(info.Type))
 558                    {
 559                        result.Add(info);
 560                    }
 561                }
 562            }
 563
 564            return result;
 565        }
 566
 567        IReadOnlyList<PluginTypeInfo> GetPluginTypes()
 568        {
 569            var result = new List<PluginTypeInfo>();
 570            var seen = new HashSet<Type>();
 571
 572            foreach (var provider in pluginProviders)
 573            {
 574                foreach (var info in provider())
 575                {
 576                    if (seen.Add(info.PluginType))
 577                    {
 578                        result.Add(info);
 579                    }
 580                }
 581            }
 582
 583            return result;
 584        }
 585
 93586        Action<object>? combinedDecoratorApplier = decoratorAppliers.Length > 0
 93587            ? services =>
 93588            {
 1318589                foreach (var applier in decoratorAppliers)
 93590                {
 339591                    applier(services);
 93592                }
 320593            }
 93594            : null;
 595
 93596        Action<object, object>? combinedOptionsRegistrar = optionsRegistrars.Length > 0
 93597            ? (services, config) =>
 93598            {
 10599                foreach (var registrar in optionsRegistrars)
 93600                {
 3601                    registrar(services, config);
 93602                }
 2603            }
 93604            : null;
 605
 93606        return new Registration(
 93607            GetInjectableTypes,
 93608            GetPluginTypes,
 93609            registryParticipantTypes,
 93610            combinedDecoratorApplier,
 93611            combinedOptionsRegistrar);
 612    }
 613}

Methods/Properties

.ctor(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>,System.Collections.Generic.IReadOnlyList`1<System.Type>,System.Action`1<System.Object>,System.Action`2<System.Object,System.Object>)
get_InjectableTypeProvider()
get_PluginTypeProvider()
get_RegistryParticipantTypes()
get_DecoratorApplier()
get_OptionsRegistrar()
.cctor()
RegisterPlugins(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>)
Register(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>)
Register(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>,System.Action`1<System.Object>)
Register(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>,System.Action`1<System.Object>,System.Action`2<System.Object,System.Object>)
Register(System.Type,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>)
Register(System.Type,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>,System.Action`1<System.Object>,System.Action`2<System.Object,System.Object>)
RegisterCore(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>,System.Collections.Generic.IReadOnlyList`1<System.Type>,System.Action`1<System.Object>,System.Action`2<System.Object,System.Object>)
RegisterExtension(System.Action`2<System.Object,System.Object>)
TryGetProviders(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>&,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>&)
TryGetProviders(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>&,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>&,System.Collections.Generic.IReadOnlyList`1<System.Type>&)
TryGetDecoratorApplier(System.Action`1<System.Object>&)
TryGetOptionsRegistrar(System.Action`2<System.Object,System.Object>&)
TryGetExtensionRegistrar(System.Action`2<System.Object,System.Object>&)
ClearRegistrationsForTesting()
BeginTestScope(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>)
BeginTestScope(System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.InjectableTypeInfo>>,System.Func`1<System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.PluginTypeInfo>>,System.Collections.Generic.IReadOnlyList`1<System.Type>)
.ctor(NexusLabs.Needlr.Generators.NeedlrSourceGenBootstrap/Registration)
Dispose()
Combine(System.Collections.Generic.IReadOnlyList`1<NexusLabs.Needlr.Generators.NeedlrSourceGenBootstrap/Registration>)