Source Generators
On this page
Nalix.Analyzers.Generators contains 7 Roslyn incremental source generators (IIncrementalGenerator) bundled inside Nalix.Abstractions. By shifting handler compilation, dependency injection, packet sizing, binary serialization, and RPC client stubs to compile time, Nalix achieves zero runtime reflection and full NativeAOT / IL2CPP compatibility.
Source Mapping
analyzers/Nalix.Analyzers.Generators/PacketHandlerGenerator.csanalyzers/Nalix.Analyzers.Generators/InstanceGenerator.csanalyzers/Nalix.Analyzers.Generators/SerializeFormatterGenerator.csanalyzers/Nalix.Analyzers.Generators/PacketRegistryGenerator.csanalyzers/Nalix.Analyzers.Generators/PacketSchemaGenerator.csanalyzers/Nalix.Analyzers.Generators/ConfigurationGenerator.csanalyzers/Nalix.Analyzers.Generators/RpcClientGenerator.csanalyzers/Nalix.Analyzers.Generators/Internal/GeneratorDiagnosticDescriptors.cs
The 7 Source Generators
| Generator | Trigger | Emitted Output | Diagnostics |
|---|---|---|---|
| Packet Handler Generator (PacketHandlerGenerator) | [PacketHandler] class with [PacketOpcode] methods | IPacketHandlerCompiler implementation + <Controller>_Inject.g.cs (InitializeDependencies()) + [ModuleInitializer] registering with PacketHandlerRegistry | NALIX067 |
| Instance Generator (InstanceGenerator) | [Injectable] class or SingletonBase<T> subclass | InstanceGenerated.Initialize() ([ModuleInitializer]) calling InstanceManager.RegisterActivator, RegisterServiceMapping, and SingletonActivatorCache.Register | NALIX063, NALIX064, NALIX065 |
| Serialization Generator (SerializeFormatterGenerator) | Class or struct with [GenerateFormatter] | IFormatter<T> + IFillableFormatter<T> implementation + [ModuleInitializer] registering with FormatterProvider | NALIX059 |
| Packet Registry Generator (PacketRegistryGenerator) | Concrete IPacket class with IPacketDeserializer<TSelf> and [Packet] or IPacketStaticOpcode | PacketRegistryGenerated.Initialize() ([ModuleInitializer]) calling PacketRegistry.RegisterGenerated<TPacket> | NALIX068 |
| Packet Schema Generator (PacketSchemaGenerator) | partial class inheriting PacketBase<TSelf> | Length override, ResetForPool() override, and static int Size (when implementing IFixedSizeSerializable) | NALIX060 |
| Configuration Generator (ConfigurationGenerator) | partial class inheriting ConfigurationLoader | CopyPropertiesTo, BindProperties, and ValidateDataAnnotations overrides | — |
| RPC Client Generator (RpcClientGenerator) | Interface annotated with [RpcService] | internal sealed class <Service>_RpcClient : <IService> registered via RpcExtensions.RegisterFactory | NALIX066 |
RPC Client Generator (RpcClientGenerator)
RpcClientGenerator (analyzers/Nalix.Analyzers.Generators/RpcClientGenerator.cs) generates a concrete client proxy class (internal sealed class <Service>_RpcClient : <IService>) for every interface decorated with [RpcService] (Nalix.Abstractions.Networking.Rpc) and registers it in a [ModuleInitializer] (<Service>_RpcClientInitializer.Initialize()) via RpcExtensions.RegisterFactory(typeof(IService), session => new <Service>_RpcClient(session)).
Supported Return Types
Each [PacketOpcode(opCode)] method in an [RpcService] interface is mapped based on its return type:
| Interface Method Return Type | Generated ITransportSession Call | Behavior |
|---|---|---|
ValueTask | new ValueTask(_session.SendAsync(request, encrypt, ct)) | Fire-and-forget one-way packet send (ValueTask). |
Task | _session.SendAsync(request, encrypt, ct) | Fire-and-forget one-way packet send (Task). |
ValueTask<TResponse> | _session.RequestAsync<TResponse>(request, options, ct: ct) | Request-response awaiting a correlated TResponse packet (ValueTask<TResponse>). |
Task<TResponse> | _session.RequestAsync<TResponse>(request, options, ct: ct).AsTask() | Request-response awaiting a correlated TResponse packet (Task<TResponse>). |
RpcCall<TResponse> | new RpcCall<TResponse>(_session, request, options) | Structured awaitable RPC call handle (GetResponseAsync() / GetAwaiter()). |
RpcStream<TResponse> | new RpcStream<TResponse>(_session, request, options) | Server-to-client streaming RPC handle (GetStreamAsync() / GetAsyncEnumerator()) where TResponse : IPacketStreamable. |
Example
using System.Threading;
using System.Threading.Tasks;
using Nalix.Abstractions.Networking.Packets;
using Nalix.Abstractions.Networking.Rpc;
[RpcService]
public interface IInventoryService
{
[PacketOpcode(0x2001)]
ValueTask<InventoryResponse> GetInventoryAsync(
InventoryRequest request,
CancellationToken ct = default);
}
At runtime, resolve the generated client proxy from any ITransportSession via CreateRpcClient<TService>():
using Nalix.SDK.Transport.Extensions;
IInventoryService inventory = session.CreateRpcClient<IInventoryService>();
InventoryResponse response = await inventory.GetInventoryAsync(
new InventoryRequest { PlayerId = 42 },
ct);