Serialization Generator
Trên trang này
SerializeFormatterGenerator (analyzers/Nalix.Analyzers.Generators/SerializeFormatterGenerator.cs) là một incremental Roslyn source generator, sinh ra các implementation IFormatter<T> và IFillableFormatter<T> lúc biên dịch cho các lớp và struct được đánh dấu [GenerateFormatter].
Ánh xạ mã nguồn
analyzers/Nalix.Analyzers.Generators/SerializeFormatterGenerator.csanalyzers/Nalix.Analyzers.Generators/Internal/GeneratorDiagnosticDescriptors.cs
Cách hoạt động
- Tìm và kiểm tra mục tiêu:
- Quét mọi lớp và struct được đánh dấu
[GenerateFormatter](đượcPacketBase<TSelf>kế thừa tự động). - Với kiểu tham chiếu (
class), kiểm tra có tồn tại methodCreate()tĩnh có thể truy cập hay không (PacketBase<TSelf>.Create()tự động thỏa điều kiện này). Nếu một lớp[GenerateFormatter]tùy chỉnh không kế thừaPacketBase<TSelf>và cũng không cóstatic T Create(), generator báo lỗiNALIX059.
- Quét mọi lớp và struct được đánh dấu
- Bố cục và thứ tự thành viên:
- Kiểm tra
[SerializePackable(SerializeLayout.Explicit)]so với[SerializePackable(SerializeLayout.Sequential)]. - Sắp xếp field và property trên toàn chuỗi kế thừa (bắt đầu với
PacketBase.Headertại[SerializeHeader(PacketHeaderOffset.Header)]có thứ tự0). - Loại trừ các thành viên
[SerializeIgnore].
- Kiểm tra
- Sinh formatter:
- Với kiểu tham chiếu (
class), implement cảIFormatter<T>vàIFillableFormatter<T>, thuê các instance pooled quaT.Create()trongDeserialize(ref DataReader)và điền dữ liệu tại chỗ quaFill(ref DataReader, T value). - Với kiểu giá trị (
struct), chỉ implementIFormatter<T>.
- Với kiểu tham chiếu (
- Đăng ký
[ModuleInitializer]tự động:- Sinh ra
GeneratedFormattersBootstrap.InitializeGeneratedFormatters(), gọi:FormatterProvider.RegisterGenerated<T>(new T_Formatter())(hoặcFormatterProvider.RegisterComplex<T>(...))FormatterProvider.RegisterCollectionFormatters<TElement>()cho mọi thành viênTElement[]hoặcList<TElement>FormatterProvider.RegisterDictionary<TKey, TValue>()cho mọi thành viênDictionary<TKey, TValue>FormatterProvider.RegisterTuple<T1, ...>()cho mọi thành viênValueTuple<...>
- Sinh ra
Ví dụ
1. Định nghĩa gói tin nguồn
using Nalix.Abstractions.Networking.Packets;
using Nalix.Abstractions.Serialization;
using Nalix.Codec.DataFrames;
[Packet(0x1001)]
[GenerateFormatter]
[SerializePackable(SerializeLayout.Sequential)]
public sealed partial class DynamicHintStringPacket : PacketBase<DynamicHintStringPacket>, IPacketStaticOpcode
{
public static ushort StaticOpCode => 0x1001;
[SerializeDynamicSize(64)]
public string Message { get; set; } = string.Empty;
}
2. Mã formatter được sinh ra
[StackTraceHidden]
[DebuggerStepThrough]
[SkipLocalsInit]
internal sealed class DynamicHintStringPacketFormatter :
IFillableFormatter<DynamicHintStringPacket>,
IFormatter<DynamicHintStringPacket>
{
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void Serialize(ref DataWriter writer, in DynamicHintStringPacket value)
{
ArgumentNullException.ThrowIfNull(value, "value");
// PacketHeader 6 byte (Order 0) được ghi đầu tiên
(ref writer).WriteUnmanaged(value.Header);
IFormatter<string> formatter = FormatterProvider.Get<string>();
string message = value.Message;
formatter.Serialize(ref writer, in message);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public DynamicHintStringPacket Deserialize(ref DataReader reader)
{
// Thuê một instance từ ObjectPoolManager qua PacketBase<TSelf>.Create()
DynamicHintStringPacket instance = PacketBase<DynamicHintStringPacket>.Create();
this.Fill(ref reader, instance);
return instance;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void Fill(ref DataReader reader, DynamicHintStringPacket value)
{
ArgumentNullException.ThrowIfNull(value, "value");
value.Header = (ref reader).ReadUnmanaged<PacketHeader>();
value.Message = FormatterProvider.Get<string>().Deserialize(ref reader);
}
}
Chẩn đoán được phát ra
| ID | Tiêu đề | Mức độ | Nguyên nhân |
|---|---|---|---|
NALIX059 | Thiếu method Create() tĩnh | Lỗi | Một kiểu tham chiếu được đánh dấu [GenerateFormatter] không định nghĩa method factory Create() tĩnh. |