diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs index 196fca38..3fc882f7 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs @@ -8,13 +8,14 @@ using AxibugEmuOnline.Client.Common; namespace AxibugEmuOnline.Client.Network { - public class NetMsg { private static NetMsg instance = new NetMsg(); public static NetMsg Instance { get { return instance; } } - private Dictionary> netEventDic = new Dictionary>(128); + // 使用强类型字典存储委托,避免DynamicInvoke + private Dictionary>> netEventDic = new Dictionary>>(128); + private Dictionary>> delegateWrappers = new Dictionary>>(); private Queue> queueNetMsg = new Queue>(); public static object lockQueueNetMsg = new object(); @@ -22,60 +23,54 @@ namespace AxibugEmuOnline.Client.Network private Queue queueEventFromNet = new Queue(); public static object lockQueueEventFromNet = new object(); - private NetMsg() { } private static Dictionary cmd2MsgTypeDict = new Dictionary(); - private static Type GetTypeByCmd(int cmd, List delegates) - { - if (cmd2MsgTypeDict.TryGetValue(cmd, out var type)) return type; - var paramters = delegates.First().Method.GetParameters(); - if (paramters.Length != 0) - { - var protoType = paramters[0].ParameterType; - if (!protoType.IsInterface && !protoType.IsAbstract) - { - cmd2MsgTypeDict[cmd] = protoType; - return protoType; - } - } - - return null; - } - #region RegisterMsgEvent public void RegNetMsgEvent(int cmd, Action callback) where T : IMessage { - InterRegNetMsgEvent(cmd, callback); + // 创建类型安全的包装委托,避免DynamicInvoke + Action wrappedCallback = (message) => { callback((T)message); }; + + // 缓存包装委托以便后续取消注册时使用 + if (!delegateWrappers.ContainsKey(typeof(T))) + { + delegateWrappers[typeof(T)] = new Dictionary>(); + } + delegateWrappers[typeof(T)][callback] = wrappedCallback; + InterRegNetMsgEvent(cmd, wrappedCallback); + SetTypeByCmd(cmd, callback); } - private void InterRegNetMsgEvent(int cmd, Delegate callback) + private void InterRegNetMsgEvent(int cmd, Action callback) { if (netEventDic.ContainsKey(cmd)) { - if (netEventDic[cmd].IndexOf(callback) < 0) - { + if (!netEventDic[cmd].Contains(callback)) netEventDic[cmd].Add(callback); - } } else { - netEventDic.Add(cmd, new List() { callback }); + netEventDic.Add(cmd, new HashSet>() { callback }); } } #endregion #region UnregisterCMD - public void UnregisterCMD(int evt, Action callback) + public void UnregisterCMD(int cmd, Action callback) where T : IMessage { - Delegate tempDelegate = callback; - InterUnregisterCMD(evt, tempDelegate); + if (delegateWrappers.TryGetValue(typeof(T), out var wrapperDict) && + wrapperDict.TryGetValue(callback, out var wrappedCallback)) + { + InterUnregisterCMD(cmd, wrappedCallback); + wrapperDict.Remove(callback); + } } - private void InterUnregisterCMD(int cmd, Delegate callback) + private void InterUnregisterCMD(int cmd, Action callback) { if (netEventDic.ContainsKey(cmd)) { @@ -85,7 +80,6 @@ namespace AxibugEmuOnline.Client.Network } #endregion - public void NextNetEvent() { DequeueNesMsg(); @@ -193,49 +187,73 @@ namespace AxibugEmuOnline.Client.Network App.log.Error("错误:" + errMsg); } - //如果报错,则不往前继续推进 if (err > ErrorCode.ErrorOk) return; - List eventList = GetNetEventDicList(cmd); - if (eventList != null) + HashSet> eventList = GetNetEventDicList(cmd); + if (eventList != null && eventList.Count > 0) { - Type protoType = GetTypeByCmd(cmd, eventList); - foreach (Delegate callback in eventList) + // 获取消息类型 + Type protoType = GetTypeByCmd(cmd); + if (protoType == null) { - try + App.log.Error($"无法确定命令 {cmd} 的消息类型"); + return; + } + IMessage protobufMsg = ProtoBufHelper.DeSerizlizeFromPool(arg, protoType); + + try + { + // 使用强类型调用,避免DynamicInvoke的性能开销 + foreach (Action callback in eventList) { - IMessage protobufMsg = ProtoBufHelper.DeSerizlizeFromPool(arg, protoType); - //((Action)callback)(protobufMsg); - callback.DynamicInvoke(protobufMsg); - ProtoBufHelper.ReleaseToPool(protobufMsg); - //((Action)callback)(arg); - } - catch (Exception e) - { - App.log.Error(e.ToString()); + try + { + callback(protobufMsg); + } + catch (Exception e) + { + App.log.Error($"处理网络消息时出错 (CMD: {cmd}): {e}"); + } } } + finally + { + ProtoBufHelper.ReleaseToPool(protobufMsg); + } } } #endregion + /// + /// 设置网络消息类型 + /// + /// + /// + /// + private static void SetTypeByCmd(int cmd, Action callback) where T : IMessage + { + var paramters = callback.Method.GetParameters(); + if (paramters.Length != 0) + { + var protoType = paramters[0].ParameterType; + if (!protoType.IsInterface && !protoType.IsAbstract) + cmd2MsgTypeDict[cmd] = protoType; + } + } + private static Type GetTypeByCmd(int cmd) + { + if (cmd2MsgTypeDict.TryGetValue(cmd, out var type)) return type; + return null; + } /// /// 获取所有事件 /// - /// - /// - private List GetNetEventDicList(int cmd) + private HashSet> GetNetEventDicList(int cmd) { - if (netEventDic.ContainsKey(cmd)) - { - List tempList = netEventDic[cmd]; - if (null != tempList) - { - return tempList; - } - } + if (netEventDic.TryGetValue(cmd, out var tempList) && tempList != null) + return tempList; return null; } } -} +} \ No newline at end of file