Packet Registry Generator
On this page
PacketRegistryGenerator (analyzers/Nalix.Analyzers.Generators/PacketRegistryGenerator.cs) is an incremental Roslyn source generator that discovers all concrete packet classes in a compilation, checks for duplicate StaticOpCode values (NALIX068), and emits a [ModuleInitializer] that registers each packet’s Deserialize delegate with PacketRegistry.
Source Mapping
analyzers/Nalix.Analyzers.Generators/PacketRegistryGenerator.csanalyzers/Nalix.Analyzers.Generators/Internal/GeneratorDiagnosticDescriptors.cssrc/Nalix.Codec/DataFrames/PacketRegistry.cs
How It Works
- Packet Discovery:
- Scans the compilation for non-abstract classes implementing
IPacketandIPacketDeserializer<TSelf>(such asPacketBase<TSelf>subclasses) that have[Packet](AutoRegister != false) or implementIPacketStaticOpcode.
- Scans the compilation for non-abstract classes implementing
- Compile-Time Opcode Collision Check (
NALIX068):- Extracts
StaticOpCodevalues across all discovered packet classes in the compilation. If two packet classes declare the sameStaticOpCode, reports errorNALIX068.
- Extracts
- Module Initializer Registration:
- Emits
PacketRegistryGenerated.Initialize()([ModuleInitializer]) inPacketRegistryGenerated.g.cs, callingPacketRegistry.RegisterGenerated<TPacket>("Namespace.TPacket", static raw => TPacket.Deserialize(raw))for each discovered packet type.
- Emits
Generated Code Structure
// <auto-generated/>
#nullable enable
using System.Runtime.CompilerServices;
using Nalix.Codec.DataFrames;
namespace Nalix.Generated
{
internal static class PacketRegistryGenerated
{
[ModuleInitializer]
internal static void Initialize()
{
PacketRegistry.RegisterGenerated<global::HelloWorld.Contracts.HelloRequestPacket>(
"HelloWorld.Contracts.HelloRequestPacket",
static raw => global::HelloWorld.Contracts.HelloRequestPacket.Deserialize(raw));
PacketRegistry.RegisterGenerated<global::HelloWorld.Contracts.HelloResponsePacket>(
"HelloWorld.Contracts.HelloResponsePacket",
static raw => global::HelloWorld.Contracts.HelloResponsePacket.Deserialize(raw));
}
}
}
Runtime Activation (PacketRegistry.Build())
[ModuleInitializer] stages every assembly’s generated packet entries at module load time. Calling PacketRegistry.Build() (invoked automatically by NetworkApplicationBuilder.Build() and TransportSession, or manually in standalone tests) compiles the staged registrations into the lock-free PacketDeserializer?[65536] lookup table:
using Nalix.Codec.DataFrames;
// Finalizes the O(1) 65,536-entry opcode lookup table
PacketRegistry.Build();
Diagnostic Emitted
| ID | Title | Severity | Cause |
|---|---|---|---|
NALIX068 | Duplicate packet StaticOpCode | Error | Two or more packet classes in the compilation define the same StaticOpCode value. |