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.