Tài liệu

Packet Registry Generator

Thời gian đọc 2 phút Gói: Nalix.Analyzers
Trên trang này

PacketRegistryGenerator (analyzers/Nalix.Analyzers.Generators/PacketRegistryGenerator.cs) là một incremental Roslyn source generator, phát hiện mọi lớp gói tin cụ thể trong một compilation, kiểm tra giá trị StaticOpCode bị trùng (NALIX068), và sinh ra một [ModuleInitializer] đăng ký delegate Deserialize của từng gói tin với PacketRegistry.

Ánh xạ mã nguồn

  • analyzers/Nalix.Analyzers.Generators/PacketRegistryGenerator.cs
  • analyzers/Nalix.Analyzers.Generators/Internal/GeneratorDiagnosticDescriptors.cs
  • src/Nalix.Codec/DataFrames/PacketRegistry.cs

Cách hoạt động

  1. Phát hiện gói tin:
    • Quét compilation để tìm các lớp không abstract, implement IPacket và IPacketDeserializer<TSelf> (chẳng hạn các lớp con của PacketBase<TSelf>), và có [Packet] (AutoRegister != false) hoặc implement IPacketStaticOpcode.
  2. Kiểm tra trùng opcode lúc biên dịch (NALIX068):
    • Lấy giá trị StaticOpCode của mọi lớp gói tin đã phát hiện trong compilation. Nếu hai lớp gói tin khai báo cùng một StaticOpCode, báo lỗi NALIX068.
  3. Đăng ký Module Initializer:
    • Sinh ra PacketRegistryGenerated.Initialize() ([ModuleInitializer]) trong PacketRegistryGenerated.g.cs, gọi PacketRegistry.RegisterGenerated<TPacket>("Namespace.TPacket", static raw => TPacket.Deserialize(raw)) cho mỗi kiểu gói tin đã phát hiện.

Cấu trúc mã được sinh ra

// <auto-generated/>
#nullable enable
using System.Runtime.CompilerServices;
using Nalix.Codec.DataFrames;

namespace Nalix.Generated
{
    internal static class PacketRegistryGenerated
    {
        [ModuleInitializer]
        internal static void Initialize()
        {
            PacketRegistry.RegisterGenerated<global::HelloWorld.Contracts.HelloRequestPacket>(
                "HelloWorld.Contracts.HelloRequestPacket",
                static raw => global::HelloWorld.Contracts.HelloRequestPacket.Deserialize(raw));

            PacketRegistry.RegisterGenerated<global::HelloWorld.Contracts.HelloResponsePacket>(
                "HelloWorld.Contracts.HelloResponsePacket",
                static raw => global::HelloWorld.Contracts.HelloResponsePacket.Deserialize(raw));
        }
    }
}

Kích hoạt lúc chạy (PacketRegistry.Build())

[ModuleInitializer] lưu tạm các mục gói tin được sinh ra của mọi assembly khi module được nạp. Gọi PacketRegistry.Build() (được gọi tự động bởi NetworkApplicationBuilder.Build() và TransportSession, hoặc gọi thủ công trong các bài kiểm thử độc lập) sẽ biên dịch các đăng ký đã lưu tạm thành bảng tra cứu không khóa PacketDeserializer?[65536]:

using Nalix.Codec.DataFrames;

// Hoàn tất bảng tra cứu opcode O(1) gồm 65.536 mục
PacketRegistry.Build();

Chẩn đoán được phát ra

IDTiêu đềMức độNguyên nhân
NALIX068StaticOpCode của gói tin bị trùngLỗiHai hoặc nhiều lớp gói tin trong compilation khai báo cùng một giá trị StaticOpCode.

API liên quan