Tuần tự hóa gói tin
Trên trang này
Không gian tên: Nalix.Codec.Serialization
Assembly: Nalix.Codec
Trang này giải thích cách SerializeFormatterGenerator, LiteSerializer và FormatterProvider tuần tự hóa và giải tuần tự hóa các lớp gói tin, struct và collection lồng nhau.
Ánh xạ mã nguồn
analyzers/Nalix.Analyzers.Generators/SerializeFormatterGenerator.cssrc/Nalix.Codec/Serialization/LiteSerializer.cssrc/Nalix.Codec/Serialization/FormatterProvider.cssrc/Nalix.Codec/DataFrames/PacketBase.cs
Nhóm kiểu được hỗ trợ
- Nguyên thủy không quản lý & struct:
char,byte,sbyte,short,ushort,int,uint,long,ulong,float,double,decimal,bool,Guid,DateOnly,DateTime,TimeOnly,TimeSpan,DateTimeOffset,Bytes32,PacketHeader, và các kiểustructkhông quản lý do người dùng định nghĩa. - Chuỗi:
stringvàstring[](StringFormatter,StringArrayFormatter). - Kiểu giá trị nullable:
T?vàT?[](NullableFormatter<T>,NullableArrayFormatter<T>,NullableValueListFormatter<T>). - Enum: Mọi
enumcó kiểu nền làbyte,sbyte,short,ushort,int,uint,longhoặculong(EnumFormatter<T>). - Collection:
T[](ArrayFormatter<T>choTkhông quản lý,ReferenceArrayFormatter<T>cho kiểu tham chiếu)List<T>(ListFormatter<T>choTkhông quản lý,ReferenceListFormatter<T>cho kiểu tham chiếu)Dictionary<TKey, TValue>(DictionaryFormatter<TKey, TValue>)Queue<T>,Stack<T>,HashSet<T>(hỗ trợ choTkhông quản lý vàstring)Memory<T>vàReadOnlyMemory<T>(hỗ trợ choTkhông quản lý)
- Tuple:
ValueTuplecó số đối từ 2 đến 5 (ValueTupleFormatter<...>). - Lớp & struct phức tạp: Mọi lớp hoặc struct được chú thích
[GenerateFormatter](bao gồm mọi lớp con củaPacketBase<TSelf>).
Mô hình thành viên lúc biên dịch ([GenerateFormatter])
Nalix không dùng reflection lúc chạy hay System.Reflection.Emit để tuần tự hóa đối tượng. Thay vào đó, SerializeFormatterGenerator kiểm tra các kiểu được đánh dấu [GenerateFormatter] ngay lúc biên dịch:
SerializeLayout.Explicit(mặc định cho[SerializePackable(SerializeLayout.Explicit)]):- Chỉ các trường và thuộc tính có
[SerializeOrder(n)](hoặc[SerializeHeader]) được tuần tự hóa, sắp xếp theo thứ tự tăng dần củaOrder. PacketBase<TSelf>đặtHeader(PacketHeader) ở vị trí0qua[SerializeHeader(0)]. Các trường người dùng trong lớp con củaPacketBase<TSelf>cũng bắt đầu[SerializeOrder]từ0(trình sinh luôn đặtHeaderlên đầu trước các thành viên người dùng).- Thành viên công khai không có
[SerializeOrder]hoặc[SerializeIgnore]sẽ kích hoạt cảnh báo analyzerNALIX013.
- Chỉ các trường và thuộc tính có
SerializeLayout.Sequential([SerializePackable(SerializeLayout.Sequential)]):- Tuần tự hóa mọi trường instance có thể truy cập và thuộc tính tự động theo thứ tự khai báo xuyên suốt chuỗi kế thừa, bỏ qua các thành viên có
[SerializeIgnore].
- Tuần tự hóa mọi trường instance có thể truy cập và thuộc tính tự động theo thứ tự khai báo xuyên suốt chuỗi kế thừa, bỏ qua các thành viên có
- Pooling kiểu tham chiếu (
Create()vàIFillableFormatter<T>):- Kiểu tham chiếu được đánh dấu
[GenerateFormatter]phải có phương thức tĩnhCreate()(được thực thi bởi lỗiNALIX059; được cung cấp tự động bởiPacketBase<TSelf>.Create()). - Formatter lớp được sinh ra triển khai cả
IFormatter<T>vàIFillableFormatter<T>, cho phépPacketBase<TSelf>.DeserializevàLiteSerializer.Fillđiền dữ liệu vào instance gói tin lấy từ pool tại chỗ mà không cấp phát bộ nhớ.
- Kiểu tham chiếu được đánh dấu
Luồng phân giải
flowchart LR
A["PacketBase<TSelf>.Serialize / Deserialize"] --> B["LiteSerializer"]
B --> C["RootFormatterCache<T>"]
C --> D["FormatterProvider.Get<T>()"]
D --> E["Pre-registered / Source-Generated IFormatter<T>"]
E --> F["DataWriter / DataReader"]Ví dụ: gói tin có struct lồng nhau và collection
using System.Collections.Generic;
using Nalix.Abstractions.Networking.Packets;
using Nalix.Abstractions.Serialization;
using Nalix.Codec.DataFrames;
[GenerateFormatter]
[SerializePackable(SerializeLayout.Sequential)]
public partial struct InventoryItem
{
public uint ItemId { get; set; }
public ushort Quantity { get; set; }
}
[Packet]
[GenerateFormatter]
[SerializePackable(SerializeLayout.Explicit)]
public sealed partial class InventorySyncPacket : PacketBase<InventorySyncPacket>, IPacketStaticOpcode
{
public static ushort StaticOpCode => 0x2010;
[SerializeOrder(0)]
public ulong AccountId { get; set; }
[SerializeOrder(1)]
public List<InventoryItem> Items { get; set; } = [];
}