Schema 元数据
本页介绍 C# 生成序列化器的 Schema 元数据。
[ForyStruct] 和 [ForyField]
使用 [ForyStruct] 启用源码生成序列化器。使用 [ForyField] 分配可选、稳定的非负字段 ID,或覆盖字段所用的 Fory Schema 类型。
外部类型序列化在本地抽象序列化器声明上设置 Target。该声明的属性定义字段名称、ID、Schema 描述符和可空性。独立声明还定义其 Evolving 设置。外部 BaseOnly 声明不能设置 Evolving;该设置由每个具体派生类型负责。目标提供运行时值和直接访问的成员。
[ForyStruct(Target = typeof(ThirdParty.User))]
internal abstract class UserSerializer
{
[ForyField(
1,
TargetDeclaringType = typeof(ThirdParty.User),
TargetMemberName = "<Name>k__BackingField")]
public abstract string Name { get; }
}
继承字段
具体类序列化器只有一个字段列表,其中包含自身字段以及每个带注解基类中选择的字段。同一个扁平列表决定字段顺序、Schema 哈希和兼容元数据。
属性重写只产生一个逻辑字段。最近的、带有 [ForyField] 的重写提供 ID 和 Schema 描述符。使用 new 隐藏的字段和成员仍彼此独立,必须使用唯一 ID 或唯一的规范化名称。重复 ID 和重复的名称标识会导致生成错误。
修改带注解基类的编码成员会改变每个派生 Schema。更新基类包后,请重新构建包含派生序列化器的程序集。
using Apache.Fory;
using S = Apache.Fory.Schema.Types;
[ForyStruct]
public sealed class Metrics
{
[ForyField(Type = typeof(S.UInt32))]
public uint Count { get; set; }
[ForyField(Type = typeof(S.Tagged<S.UInt64>))]
public ulong TraceId { get; set; }
public long LatencyMicros { get; set; }
}
Id 是可选的。省略时,兼容模式仍按名称匹配字段。
using Apache.Fory;
using S = Apache.Fory.Schema.Types;
[ForyStruct]
public sealed class NestedMetrics
{
[ForyField(Type = typeof(S.Map<S.Fixed<S.UInt32>, S.List<S.Tagged<S.UInt64>>>))]
public Dictionary<uint, List<ulong?>?> Values { get; set; } = [];
[ForyField(3, Type = typeof(S.UInt64))]
public ulong StableCount { get; set; }
}
Schema 描述符类型
Schema 描述符位于 Apache.Fory.Schema.Types 下,仅作为元数据使用。它们不会替代普通 C# 载体类型。
常用标量描述符包括:
S.Int32,S.UInt32S.Int64,S.UInt64S.Float16,S.BFloat16,S.Float32,S.Float64
容器描述符可以组合:
S.Fixed<TScalar>和S.Tagged<TScalar>用于标量整数编码S.List<TElement>S.Set<TElement>S.Map<TKey, TValue>S.Array<TElement>
密集数组字段使用 S.Array<TElement>,例如 S.Array<S.Int32> 或 S.Array<S.BFloat16>。
可空性来自 C# 载体类型。可空列表元素使用 List<ulong?>,map 需要可空 key 时使用 NullableKeyDictionary<TKey, TValue>。
[ForyUnion] 和 [ForyCase]
生成的 union case 使用 [ForyCase] 同时指定稳定 case ID 和可选的 case 载荷 Schema 类型。不要在 union case 载荷成员上添加 [ForyField]。已知 case 的 record 名称使用 PascalCase FDL case 名称;需要避免名称冲突时,载荷类型使用限定引用。类型化 union 必须声明至少一个非 Unknown case;Unknown(UnknownCase) 只是 Fory 提供的向前兼容载体。该标记只选择载体,不会在 Schema case 表中增加条目。
using Apache.Fory;
using S = Apache.Fory.Schema.Types;
[ForyUnion]
public abstract partial record Shape
{
private Shape() {}
[ForyUnknownCase]
public sealed partial record Unknown(UnknownCase Value) : Shape;
[ForyCase(0)]
public sealed partial record Circle(global::example.Circle Value) : Shape;
[ForyCase(1, Type = typeof(S.Fixed<S.Int32>))]
public sealed partial record Code(int Value) : Shape;
}
可空性和引用跟踪
- 字段可空性来自 C# 类型可空性(
string?、可空值类型等)。 - 使用
ForyBuilder.TrackRef(...)配置引用跟踪。