< Summary

Information
Class: MultiProjectApp.Features.Notifications.NotificationSinkRegistrations
Assembly: MultiProjectApp.Features.Notifications
File(s): /home/runner/work/needlr/needlr/src/Examples/MultiProjectApp/MultiProjectApp.Features.Notifications/CrossGeneratedPlugins.cs
Line coverage
100%
Covered lines: 9
Uncovered lines: 0
Coverable lines: 9
Total lines: 75
Line coverage: 100%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Initialize()100%22100%

File(s)

/home/runner/work/needlr/needlr/src/Examples/MultiProjectApp/MultiProjectApp.Features.Notifications/CrossGeneratedPlugins.cs

#LineLine coverage
 1using System.Runtime.CompilerServices;
 2
 3using NexusLabs.Needlr.Generators;
 4
 5namespace MultiProjectApp.Features.Notifications;
 6
 7/// <summary>
 8/// A sink that receives and processes notifications emitted by the application.
 9/// </summary>
 10/// <remarks>
 11/// This interface exists to demonstrate the <c>RegisterPlugins()</c> cross-generator pattern.
 12/// In a real scenario a second generator (such as a CacheProviderGenerator) would
 13/// emit types implementing this interface, and TypeRegistryGenerator would not be able to see
 14/// them because Roslyn generators operate on the original compilation in isolation.
 15/// </remarks>
 16public interface INotificationSink
 17{
 18    void OnNotification(string recipient, string message);
 19}
 20
 21/// <summary>
 22/// Writes notifications to the console as an audit trail.
 23/// </summary>
 24/// <remarks>
 25/// In the multi-generator scenario this type would be emitted by a second source generator.
 26/// TypeRegistryGenerator can see it here because it is hand-written, but the
 27/// <c>NotificationSinkRegistrations</c> class below demonstrates the pattern a generated
 28/// <c>[ModuleInitializer]</c> would use.
 29/// </remarks>
 30public sealed record AuditLogNotificationSink : INotificationSink
 31{
 32    public void OnNotification(string recipient, string message) =>
 33        Console.WriteLine($"[Audit] {recipient}: {message}");
 34}
 35
 36/// <summary>
 37/// Simulates the module initializer that a second source generator would emit to register
 38/// its plugin types with Needlr at runtime, bypassing the Roslyn generator isolation boundary.
 39/// </summary>
 40/// <remarks>
 41/// <para>
 42/// Roslyn source generators run against the original compilation — a generator cannot see types
 43/// emitted by another generator in the same build. This means <c>TypeRegistryGenerator</c>
 44/// cannot include types produced by a second generator in the TypeRegistry.
 45/// </para>
 46/// <para>
 47/// The workaround is runtime registration: the second generator emits a
 48/// <c>[ModuleInitializer]</c> (like the one below) that calls
 49/// <c>NeedlrSourceGenBootstrap.RegisterPlugins()</c>. All module initializers complete before
 50/// any user code runs, so the plugins are available by the time the application calls
 51/// <c>IPluginFactory.CreatePluginsFromAssemblies&lt;T&gt;()</c>.
 52/// </para>
 53/// <para>
 54/// <c>NeedlrSourceGenBootstrap.Combine()</c> deduplicates across all registrations, so if
 55/// TypeRegistryGenerator also sees the type (as in this example where it is hand-written),
 56/// only one instance appears in the merged provider.
 57/// </para>
 58/// </remarks>
 59internal static class NotificationSinkRegistrations
 60{
 61#pragma warning disable CA2255
 62    [ModuleInitializer]
 63    internal static void Initialize()
 64#pragma warning restore CA2255
 65    {
 866        NeedlrSourceGenBootstrap.RegisterPlugins(static () =>
 2467        [
 2468            new PluginTypeInfo(
 2469                typeof(AuditLogNotificationSink),
 2470                [typeof(INotificationSink)],
 171                static () => new AuditLogNotificationSink(),
 2472                [])
 2473        ]);
 874    }
 75}

Methods/Properties

Initialize()