跳到主要内容
版本:1.5.0

自定义序列化器

当某个类型不是通过 [ForyStruct] 生成,或者需要专门的编码方式时,可以使用自定义序列化器。

外部类型序列化可为可变的第三方目标类型生成序列化器,包括精确映射私有字段或已重命名字段。对于不可变、仅能通过构造函数或工厂创建、包含 readonlyinit-only 成员、需要类型转换或采用自定义编码格式的目标类型,请使用自定义序列化器。在 .NET 8 上,如果某个外部私有编码字段的声明所在类型或访问器签名使用了泛型,也需要使用自定义序列化器。只用于存储的精确映射不会生成私有访问器。

实现 Serializer<T>

using Apache.Fory;

public sealed class Point
{
public int X { get; set; }
public int Y { get; set; }
}

public sealed class PointSerializer : Serializer<Point>
{
public override Point DefaultValue => new();

public override void WriteData(WriteContext context, in Point value, bool hasGenerics)
{
context.Writer.WriteVarInt32(value.X);
context.Writer.WriteVarInt32(value.Y);
}

public override Point ReadData(ReadContext context)
{
return new Point
{
X = context.Reader.ReadVarInt32(),
Y = context.Reader.ReadVarInt32(),
};
}
}

注册序列化器

Fory fory = Fory.Builder().Build();
fory.Register<Point, PointSerializer>(200);

Point value = new() { X = 10, Y = 20 };
byte[] payload = fory.Serialize(value);
Point decoded = fory.Deserialize<Point>(payload);

当对端使用类型名称而不是数字 ID 来标识类型时,请使用接受名称参数的重载:

fory.Register<Point, PointSerializer>("com.example.Point");

序列化器行为说明

  • WriteData / ReadData 只负责处理载荷内容。
  • 除非显式重写,否则引用标志和类型信息由基类 Serializer<T>.Write / Read 处理。
  • DefaultValue 用于空值或默认值回退路径。

最佳实践

  1. 保持序列化器逻辑确定且读写对称。
  2. 对整数密集型载荷要有意识地选择 varint、fixed 或 tagged 编码。
  3. 在所有读写端都注册自定义序列化器。
  4. 对常规领域模型优先使用 [ForyStruct] 生成的序列化器。

相关主题