AOT / Trimming Support
NetMediate is compatible with NativeAOT and trimming when you stay on the source-generated, closed-type registration path.
Summary
- Use
NetMediate.SourceGenerationin the startup project. - Call
builder.Services.AddNetMediate();. - Register custom pipeline behaviors as closed types directly in DI.
- Concrete non-generic classes that implement closed generic contracts can still use
[Injectable]. - Register only generic/open service implementations manually in
builder.Services. - Keyed dispatch uses GenDI keyed-service registrations and NetMediate keyed dispatch APIs.
| Path | AOT / Trim compatible | Notes |
|---|---|---|
AddNetMediate() | ✅ Yes | Generated at compile time — no reflection |
| Closed-type pipeline behavior registrations | ✅ Yes | Register your handler with [DecoratorFor<>] directly |
Keyless Send / Notify / Request / RequestStream | ✅ Yes | Uses generated closed-type registrations |
Keyed dispatch (Send(key, ...), Request(key, ...), etc.) | ✅ Yes | GenDI keyed-service resolution (no reflection in NetMediate runtime path), fully NativeAOT + Trimming compatible |
AOT-compatible setup
Step 1: Install NetMediate.SourceGeneration
<PackageReference Include="NetMediate.SourceGeneration" Version="x.x.x.x">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>contentfiles; compile; runtime</PrivateAssets>
</PackageReference>
Step 2: Call the generated extension method
// Generated at compile time — no reflection at startup
builder.Services.AddNetMediate();
The source generator discovers all handler types in your project and emits the AddNetMediate() entrypoint, generated dispatch extensions, and any applicable framework behavior wrappers. The generated entrypoint is GenDI-first: it chains the consuming project's AddGenDIServices() output before NetMediate's own AddGenDIServices() output instead of emitting legacy Register*Handler<> calls.
Step 3: Register custom behaviors as closed types
using GenDI;
using Microsoft.Extensions.DependencyInjection;
using NetMediate;
[DecoratorFor]
public sealed class AuditCreateUserBehavior : IRequestHandler<CreateUserRequest, UserDto>
{
[Inject] public required IRequestHandler<CreateUserRequest, UserDto> Next { get; init; }
public ValueTask<UserDto> Handle(
CreateUserRequest message,
CancellationToken cancellationToken) =>
Next(message, cancellationToken);
}
builder.Services.AddNetMediate();