You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自动处理服务端TCP/UDP消息 无需手动注册字典式包处理器

自动注册消息处理器实现方案

存在通用的自动注册方案,核心通过自定义特性+反射扫描实现,无需手动维护字典注册逻辑,后续新增消息类型只需开发对应处理方法即可,无需修改注册代码,具体实现步骤如下:

步骤1:定义消息处理标记特性

首先创建自定义特性,用于标记每个消息对应的处理方法:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class PacketHandlerAttribute : Attribute
{
    public int PacketId { get; }
    
    // 直接传入ServerPackets枚举,避免手动写int的错误
    public PacketHandlerAttribute(ServerPackets packetId)
    {
        PacketId = (int)packetId;
    }
}

步骤2:给现有处理方法加标记

给ClientHandle类下的所有消息处理方法加上刚才定义的特性:

public static class ClientHandle
{
    [PacketHandler(ServerPackets.welcome)]
    public static void Welcome(Packet packet)
    {
        // 原有业务逻辑不变
    }

    [PacketHandler(ServerPackets.spawnPlayer)]
    public static void SpawnPlayer(Packet packet)
    {
        // 原有业务逻辑不变
    }

    // 其余所有消息处理方法都按上述格式添加特性即可
}

步骤3:替换手动注册逻辑为自动扫描

修改InitializeClientData方法,通过反射自动扫描所有带标记的处理方法,存入字典:

private void InitializeClientData()
{
    packetHandlers = new Dictionary<int, PacketHandler>();
    
    // 扫描程序集中所有符合要求的处理方法
    var handlerMethods = AppDomain.CurrentDomain.GetAssemblies()
        // 可根据实际情况缩小扫描范围,提升启动速度
        .Where(assembly => assembly.GetName().Name == "你的程序集名称")
        .SelectMany(assembly => assembly.GetTypes())
        // 筛选出存放处理方法的类,也可移除该条件扫描所有类
        .Where(type => type == typeof(ClientHandle))
        .SelectMany(type => type.GetMethods(BindingFlags.Public | BindingFlags.Static))
        // 只保留带PacketHandler特性的方法
        .Where(method => method.GetCustomAttribute<PacketHandlerAttribute>() != null);

    foreach (var method in handlerMethods)
    {
        var attr = method.GetCustomAttribute<PacketHandlerAttribute>();
        // 将方法转换为PacketHandler委托存入字典
        var handler = (PacketHandler)Delegate.CreateDelegate(typeof(PacketHandler), method);
        // 可加重复ID校验逻辑,避免冲突
        if (!packetHandlers.TryAdd(attr.PacketId, handler))
        {
            Debug.LogError($"重复注册消息ID:{attr.PacketId},处理方法:{method.Name}");
        }
    }

    Debug.Log($"自动初始化完成,共加载{packetHandlers.Count}个消息处理器");
}

注意事项

  • 所有处理方法的签名必须和PacketHandler委托完全一致,否则创建委托时会抛出异常
  • 反射扫描仅在程序启动时执行一次,运行时调用字典的性能和手动硬编码注册完全一致,无额外性能损耗
  • 如果处理方法存放在多个程序集中,调整扫描的Assemblies范围即可
  • 如果处理类是实例类而非静态类,需要调整GetMethods的BindingFlags参数,创建委托时传入类的实例对象

内容的提问来源于stack exchange,提问作者Yunus Emre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:06:08