如何自动处理服务端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
相关产品推荐
相关产品推荐

