Snowberry.Mediator.SourceGenerator
2.0.0
dotnet add package Snowberry.Mediator.SourceGenerator --version 2.0.0
NuGet\Install-Package Snowberry.Mediator.SourceGenerator -Version 2.0.0
<PackageReference Include="Snowberry.Mediator.SourceGenerator" Version="2.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Snowberry.Mediator.SourceGenerator" Version="2.0.0" />
<PackageReference Include="Snowberry.Mediator.SourceGenerator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Snowberry.Mediator.SourceGenerator --version 2.0.0
#r "nuget: Snowberry.Mediator.SourceGenerator, 2.0.0"
#:package Snowberry.Mediator.SourceGenerator@2.0.0
#addin nuget:?package=Snowberry.Mediator.SourceGenerator&version=2.0.0
#tool nuget:?package=Snowberry.Mediator.SourceGenerator&version=2.0.0
Snowberry.Mediator.SourceGenerator
A Roslyn incremental source generator for Snowberry.Mediator that
discovers handlers, behaviors and notification handlers at compile time and emits the registration code with
literal closed generics, eliminating all runtime reflection (Assembly.GetTypes(), Type.GetInterfaces(),
MakeGenericType). The result is fully trim- and NativeAOT-friendly: no dynamic code is executed on the generated path.
Easy setup
Reference this package plus
Snowberry.Mediatorand a DI integration package (Snowberry.Mediator.Extensions.DependencyInjectionforMicrosoft.Extensions.DependencyInjection, orSnowberry.Mediator.DependencyInjectionfor the Snowberry container).Add the opt-in attribute to your composition-root project (e.g. in
Program.csor anAssemblyInfo.cs):[assembly: SnowberryMediator]Call the generated registration with no
options.Assembliesand no hand-listed handler types:services.AddSnowberryMediator(); // default Scoped lifetime services.AddSnowberryMediator(ServiceLifetime.Singleton);
Handlers are discovered both in your project and in referenced assemblies, as long as the composition-root
project can access the type (public, or internal exposed via [InternalsVisibleTo]).
What is discovered
Types implementing any of the Snowberry.Mediator marker interfaces (IRequestHandler<,>,
IStreamRequestHandler<,>, INotificationHandler<>, IPipelineBehavior<,>, IStreamPipelineBehavior<,>),
including open-generic behaviors and open-generic notification handlers. Pipeline ordering via
[PipelineOverwritePriority] is honored, with byte-identical semantics to the reflection-based path.
The [SnowberryMediator] attribute exposes per-category toggles (all default true):
RegisterRequestHandlers, RegisterStreamRequestHandlers, RegisterNotificationHandlers,
RegisterPipelineBehaviors, RegisterStreamPipelineBehaviors.
Scoping which assemblies are scanned
By default the generator scans the current assembly and every referenced assembly that references
Snowberry.Mediator.Abstractions. To restrict discovery, set ScanReferencedAssemblies = false
and name the referenced assemblies to include with one
[assembly: SnowberryMediatorAssembly(typeof(AnyTypeInThatAssembly))] per assembly:
// Scan only this assembly plus the two named ones; ignore all other referenced handlers.
[assembly: SnowberryMediator(ScanReferencedAssemblies = false)]
[assembly: SnowberryMediatorAssembly(typeof(MyApp.Orders.PlaceOrderHandler))]
[assembly: SnowberryMediatorAssembly(typeof(MyApp.Billing.Marker))]
- The current (composition-root) assembly is always scanned because it carries the opt-in attribute.
ScanReferencedAssemblies = true(the default) scans every eligible referenced assembly;SnowberryMediatorAssemblymarkers are ignored in that mode (everything is already scanned).- Open-generic behaviors/handlers only close over request/notification types from scanned assemblies, so excluding an assembly removes both its handlers and its closure targets.
Use this to stop an unwanted referenced assembly's handlers from registering (surprise
registrations, or SBMED001 duplicate-handler errors when two assemblies handle the same request).
Per-handler service lifetime
AddSnowberryMediator(lifetime) applies one lifetime to every discovered handler. To give a
specific handler a different lifetime, register it before calling the generated entry point, because
the generated registrations use no-overwrite (TryAdd) semantics, so a pre-registered handler keeps
your lifetime:
services.AddSingleton<IRequestHandler<GetUser, string>, GetUserHandler>(); // your chosen lifetime
services.AddSnowberryMediator(); // skips the pre-registered one
Diagnostics
| ID | Severity | Meaning |
|---|---|---|
| SBMED001 | Error | Duplicate request handler for the same request/response. |
| SBMED002 | Error | Duplicate stream request handler for the same request/response. |
| SBMED101 | Info | Handler is inaccessible to the consuming assembly (add [InternalsVisibleTo]) and was skipped. |
| SBMED102 | Warning | A handler's request/response/notification type is inaccessible; the handler was skipped. |
| SBMED103 | Warning | A non-instantiable type implements a handler interface and was skipped. |
| SBMED201 | Warning | Multiple [SnowberryMediator] attributes; the first one is used. |
| SBMED202 | Info | The generator was triggered but discovered no handlers. |
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 179 | 6/1/2026 |