UnambitiousFx.Synapse.Generator
1.2.5
dotnet add package UnambitiousFx.Synapse.Generator --version 1.2.5
NuGet\Install-Package UnambitiousFx.Synapse.Generator -Version 1.2.5
<PackageReference Include="UnambitiousFx.Synapse.Generator" Version="1.2.5"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="UnambitiousFx.Synapse.Generator" Version="1.2.5" />
<PackageReference Include="UnambitiousFx.Synapse.Generator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add UnambitiousFx.Synapse.Generator --version 1.2.5
#r "nuget: UnambitiousFx.Synapse.Generator, 1.2.5"
#:package UnambitiousFx.Synapse.Generator@1.2.5
#addin nuget:?package=UnambitiousFx.Synapse.Generator&version=1.2.5
#tool nuget:?package=UnambitiousFx.Synapse.Generator&version=1.2.5
Synapse
A lightweight, high-performance mediator implementation for .NET with first-class integration with Result types.
๐ง Compatibility & support
- Dependency-free at runtime: No external runtime dependencies.
- Native AOT-compatible: Designed to work well in Native AOT scenarios (see the
examples/MinimalApi). - Supported .NET versions: Supports Microsoft LTS releases and the latest non-LTS release. See CI matrix for exact versions.
๐ฏ Features
- Lightweight Mediator โ Requests, commands, queries, and notifications with minimal allocations.
- Result-first โ Uses
UnambitiousFx.FunctionalResultfor explicit error handling. - Streaming requests โ Built-in support for streaming request/response patterns.
- Pipeline Behaviors โ Typed, untyped and conditional pipeline behaviors for requests and events.
- Dependency injection friendly โ Register handlers and behaviours via a fluent configuration API (
AddSynapse). - Outbox support โ Interfaces and helpers to implement the outbox pattern and reliable event publishing.
- Observability hooks โ Metrics and tracing integration points to capture latency and publish metrics.
- Source generator โ Optional code-generation to reduce allocations and simplify registration.
- Examples & benchmarks โ Real-world examples and performance benchmarks included.
๐ฆ Installation
dotnet add package UnambitiousFx.Synapse
๐ Quick Start
Register mediator services
Register the synapse and your handlers in Program.cs:
builder.Services.AddSynapse(cfg =>
{
cfg.AddRegisterGroup(new ManualRegisterGroup());
// Request handlers
cfg.RegisterRequestHandler<CreateTodoCommandHandler, CreateTodoCommand, Guid>()
.RegisterRequestHandler<ListTodoQueryHandler, ListTodoQuery, IEnumerable<Todo>>();
// Event handlers
cfg.RegisterEventHandler<TodoUpdatedHandler, TodoUpdated>();
// Pipeline behaviors
cfg.RegisterRequestPipelineBehavior<SimpleLoggingBehavior>();
cfg.RegisterEventPipelineBehavior<SimpleLoggingBehavior>();
});
Send requests
Use IInvoker to dispatch requests to handlers:
// Send a command that returns a value
var result = await invoker.InvokeAsync<CreateTodoCommand, Guid>(command);
// Send a command without a response
var result = await invoker.InvokeAsync<UpdateTodoCommand>(command);
// Stream results from an IStreamRequest
await foreach (var itemResult in invoker.InvokeStreamAsync<ListItemsRequest, Item>(request))
{
// itemResult is Result<Item>
}
Use handlers directly
You can also resolve IRequestHandler<TRequest, TResponse> or IRequestHandler<TRequest> from DI and call
HandleAsync directly when appropriate.
๐ Observability & Metrics
Synapse exposes hooks for recording metrics and integrates with OpenTelemetry tracing through dedicated activity sources
and metric interfaces. Consumers can provide their own ISynapseMetrics implementation or use the default which
integrates with IMeterFactory.
๐ Documentation
Full documentation is available at https://unambitiousfx.com/lib-synapse/
๐งช Examples & Benchmarks
- Examples are under the
examples/folder (Web API, Console, Native AOT example). - Benchmarks are available in
benchmarks/SynapseBenchmarkto measure throughput and compare against alternatives.
๐งฉ Extensibility
- Pipeline behaviors: implement
IRequestPipelineBehavior,IEventPipelineBehavior, or the typed/stream variants. - Registration groups: implement
IRegisterGroupto modularize and share handler registration logic. - Outbox & commits: implement
IOutboxStorage,IOutboxCommitfor transactional event persistence.
Cross-assembly pipeline behaviors
An open-generic [PipelineBehavior] is applied to every request/event/stream handler the
declaring assembly can see โ including handlers defined in referenced assemblies. The generator
emits one closed (Native-AOT-safe) registration per matching handler, so a behavior registered in
your composition root blankets the whole reference graph automatically. Constraints (e.g.
where TRequest : ISecuredRequest) still filter which handlers a behavior wraps.
This propagation flows downward only โ along the reference direction. A behavior declared in a library cannot wrap a handler in an application that references it (the library cannot see that application). Place behaviors meant to apply everywhere in the composition root.
Event behaviors (IEventPipelineBehavior<TEvent>) and stream behaviors get the same treatment โ
including where TEvent : โฆ / where TRequest : โฆ constraint filtering, so an open-generic event
behavior constrained to a marker interface only wraps events that implement it.
CQRS boundary enforcement follows the same downward propagation. Apply
[assembly: EnableSynapseCqrsBoundaryEnforcement] once at the composition root and it covers request
handlers in referenced assemblies too โ no need to repeat the attribute in every sub-project. Leaving
it on a referenced library is harmless: duplicate enforcement registrations are deduplicated at the
service-collection level (the behavior is not idempotent, so this dedup is what keeps it safe).
To opt an assembly out and restrict its behaviors (and CQRS enforcement) to same-assembly handlers,
apply [assembly: DisableSynapseCrossAssemblyBehaviors].
Handlers the generator cannot see โ those registered manually at runtime via
cfg.RegisterRequestHandler<โฆ>(), or living in an assembly the generator does not scan โ are not
covered by the attribute. Enforce them explicitly with
cfg.RegisterCqrsBoundaryEnforcement<TRequest>() (or the <TRequest, TResponse> overload) in the
composition root. The registration is closed (Native-AOT safe) and deduplicated, so it is safe to
call even for a request the generator also covers.
Ordering caveat: the
Orderproperty sorts behaviors only within a singleIRegisterGroup. Across separately composedRegisterGroups (e.g. one per assembly), pipeline position followsAddRegisterGroupcall order. CQRS boundary enforcement is registered "first" and stays outermost regardless.
Note: Transport/distributed messaging APIs are intentionally not documented here โ they may change prior to the first stable release.
๐ค Contributing
We welcome contributions! Please read CONTRIBUTING.md for standards, development setup, and the PR process.
๐ Release notes
See releases on GitHub for detailed changelogs and version history: https://github.com/UnambitiousFx/Synapse/releases
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
Made with โค๏ธ by the UnambitiousFx team
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 |
|---|---|---|
| 1.2.5 | 79 | 7/22/2026 |
| 1.2.4 | 117 | 7/20/2026 |
| 1.2.3 | 103 | 6/28/2026 |
| 1.2.2 | 112 | 6/27/2026 |
| 1.2.1 | 109 | 6/27/2026 |
| 1.2.0 | 113 | 6/26/2026 |
| 1.1.1 | 124 | 5/23/2026 |
| 1.1.0 | 108 | 5/20/2026 |
| 1.0.0 | 110 | 5/3/2026 |
| 1.0.0-beta6 | 133 | 2/5/2026 |
| 1.0.0-beta5 | 119 | 2/5/2026 |
| 1.0.0-beta4 | 119 | 2/4/2026 |
| 1.0.0-beta3 | 123 | 1/8/2026 |
| 1.0.0-beta2 | 122 | 1/6/2026 |
| 1.0.0-beta1 | 121 | 1/6/2026 |