C# Code Generation
The dotnet generator produces multi-file C# output with models, clients, server executors, and formatters.
Output Structure
For a project named MyProject, the generator creates:
MyProject.Generated/
├── MyProject.Generated.csproj
├── moduleInit.cs — typedefs, formatter registration
├── models/
├── User.cs — message classes
├── Status.cs — enum types
└── Shape.cs — union interfaces + cases
├── client/
└── UserService.client.cs — client proxy
├── server/
├── IUserService.cs — service interface
└── UserService.executor.cs — server executor
└── formatters/
├── User.formatter.cs
└── UserService.formatter.cs
Model Generation
Each msg generates a sealed class:
// From: msg User { id: u4; name: string; email: string?; } public sealed class User { public uint id { get; set; } public string name { get; set; } public IonMaybe<string> email { get; set; } }
Service Interface
Each service generates an interface:
// From: service UserService(spaceId: u4) { GetUser(userId: u4): User; } public interface IUserService : IIonService { Task<User> GetUser( uint spaceId, uint userId, CancellationToken ct = default); }
Base arguments become the first parameters. CancellationToken is always appended.
Client Proxy
Generated client proxies handle serialization and HTTP/WebSocket transport:
// Generated client proxy (simplified) internal sealed class Ion_UserService_ClientImpl : IUserService { private readonly IonClient _client; private readonly uint _spaceId; public async Task<User> GetUser(uint spaceId, uint userId, CancellationToken ct) { var request = new IonRequest("UserService", "GetUser"); // Serialize [spaceId, userId] to CBOR // POST to /ion/UserService/GetUser.unary // Deserialize CBOR response to User return result; } }
Server Executor
The executor sits between the network layer and your service implementation:
// Generated executor (simplified) internal sealed class Ion_UserService_ServiceExecutor : IServiceExecutorRouter { public async Task Execute( string method, ReadOnlyMemory<byte> payload, IIonRequestTerminator terminator) { // 1. Deserialize args from CBOR // 2. Resolve IUserService from DI // 3. Call service.GetUser(args...) // 4. Serialize result to CBOR // 5. Write response via terminator } }
Module Initialization
moduleInit.cs runs at application startup and registers all formatters, descriptors, and type aliases:
// moduleInit.cs (auto-generated) global using UserId = uint; [ModuleInitializer] internal static void Initialize() { // Register all formatters IonFormatterStorage<User>.Serialize = ...; IonFormatterStorage<User>.Deserialize = ...; // Register service descriptors IonDescriptorStorage.Register("UserService", ...); }
.csproj Generation
By default, the compiler also generates a .csproj file with the correct NuGet references. Use --no-emit-csproj to skip this if you manage the project file manually.