Skip to main content
Version: dev

C#

Output Layout

C# output is one .cs file per schema, for example:

  • <csharp_out>/addressbook/Addressbook.cs

The C# model file name uses the normalized PascalCase source file stem. For example, service.fdl generates Service.cs, order-events.fdl generates OrderEvents.cs, and 123-schema.fdl generates Schema123Schema.cs.

Type Generation

Messages generate [ForyStruct] classes with C# properties and byte helpers:

[ForyStruct]
public sealed partial class Person
{
public string Name { get; set; } = string.Empty;
public int Id { get; set; }
public List<Person.PhoneNumber> Phones { get; set; } = new();
public Animal Pet { get; set; } = null!;

public byte[] ToBytes() { ... }
public static Person FromBytes(byte[] data) { ... }
}

Unions generate [ForyUnion] ADTs. Unknown(UnknownCase) is the Fory-provided forward-compatibility carrier marked with [ForyUnknownCase]. The marker only selects the carrier and does not add an entry to the schema case table. Schema-defined cases use non-negative [ForyCase] IDs. If a case needs non-default schema encoding, the generated [ForyCase] carries Type. Known case record names are PascalCase FDL case names; payload types are emitted as qualified references when needed to avoid name conflicts. A typed union must have at least one non-Unknown case.

[ForyUnion]
public abstract partial record Animal
{
private Animal() {}

[ForyUnknownCase]
public sealed partial record Unknown(UnknownCase Value) : Animal;

[ForyCase(0)]
public sealed partial record Dog(global::addressbook.Dog Value) : Animal;

[ForyCase(1)]
public sealed partial record Cat(global::addressbook.Cat Value) : Animal;
}

Module Installation

Each schema generates a module class that installs imported modules first and then registers the local schema types:

public static class AddressbookForyModule
{
public static void Install(Fory fory)
{
fory.Register<addressbook.Animal>((uint)106);
fory.Register<addressbook.Person>((uint)100);
// ...
}
}

The C# model file basename and module class both use the normalized source file stem. They do not use csharp_namespace and they do not use gRPC service names. For example, service.fdl generates Service.cs and ServiceForyModule, while order-events.fdl generates OrderEvents.cs and OrderEventsForyModule. A gRPC service named Greeter generates the service companion GreeterGrpc.cs; it does not change the schema module name. To get GreeterForyModule, name the schema file greeter.fdl or Greeter.fdl.

This source-file rule lets several schemas target the same C# namespace without colliding. No namespace-derived or service-derived module alias is generated.

When explicit type IDs are not provided, generated installation uses computed numeric IDs (same behavior as other targets).

gRPC Service Companions

With --grpc, C# emits one <ServiceName>Grpc.cs per service. Its static service holder contains descriptors, <ServiceName>Base, <ServiceName>Client, and both BindService overloads. See C# gRPC for hosting, clients, dependencies, and streaming.