Native AOT & trimming
Reflection-based assembly scanning is what makes most mediators unusable under trimming. Mediant ships a source generator that does the same work at compile time.
dotnet add package Mediant.SourceGenerator// Generated: registers every handler and precomputes Send/Publish/Stream dispatch.builder.Services.AddMediantGenerated();That replaces AddMediant(cfg => cfg.RegisterServicesFromAssembly(...)). No assembly scanning, no runtime
code generation, nothing for the trimmer to guess at.
What you get
- Every
ICommandHandler,IQueryHandler,IRequestHandler,INotificationHandlerandIStreamRequestHandlerin the compilation is discovered and registered. - Dispatch tables for
Send,PublishandCreateStreamare emitted as plain switch code. - The core
Mediantassembly is markedIsAotCompatible, and its dispatch path is verified trim- and AOT-clean by the analyzers.
The reflection path still works — keep AddMediant(...) for ordinary JIT scenarios if you prefer it.
Under trimming or Native AOT, use AddMediantGenerated().
JSON serialization
Three features serialize to JSON: the caching behavior, the idempotency store, and the outbox. Under AOT
they need a JsonSerializerContext rather than reflection-based System.Text.Json.
[JsonSerializable(typeof(GetOrderById))][JsonSerializable(typeof(Order))][JsonSerializable(typeof(OrderCreatedEvent))]internal partial class AppJsonContext : JsonSerializerContext;Then pass its options wherever they’re accepted:
builder.Services.AddMediantAllBehaviors(opts =>{ opts.SerializerOptions = AppJsonContext.Default.Options;});Register a type for every request that is [Cacheable] or [Idempotent], every response those return,
and every notification that goes through the outbox.
Publishing
dotnet publish -c Release -r linux-x64 -p:PublishAot=trueThen check the build output. Trim and AOT warnings are the contract: if Mediant produces one, it is a
bug worth reporting.
<PropertyGroup> <PublishAot>true</PublishAot> <TrimmerSingleWarn>false</TrimmerSingleWarn></PropertyGroup>What doesn’t work
cfg.AddOpenBehavior(typeof(MyBehavior<,>)) closes an open generic at runtime. That is fine under JIT and
under the trimmer with the generator (the closed types are rooted), but if you construct handler or
behavior types dynamically yourself, the trimmer cannot see them. Keep that reflection out of the hot
path, or root the types explicitly.