美文网首页
每日一学20——凉鞋的简易消息机制

每日一学20——凉鞋的简易消息机制

作者: ShawnWeasley | 来源:发表于2020-07-13 15:34 被阅读0次

    学习来源:https://liangxiegame.com/zhuanlan/content/detail/61edfc3b-05df-45b2-9b71-2f2d42835b6a

    把凉鞋的代码整理了一下,事件收发写到了一起,代码如下:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class NewBehaviourScript1 : MonoBehaviour, IMsgReceiver, IMsgSender
    {
        void Start()
        {
            //注册消息,其中string是消息名,ReceiveMsg是委托回调
            this.RegisterLogicMsg("Receiver Show Sth", ReceiveMsg);
            this.SendLogicMsg("Receiver Show Sth", "你好", "世界");
        }
    
        private void ReceiveMsg(object[] args)
        {
            foreach (var arg in args)
            {
                Debug.Log(arg);
            }
        }
    }
    
    public interface IMsgReceiver
    {
    }
    
    public interface IMsgSender
    {
    }
    
    
    public static class MsgDispatcher
    {
        /// <summary>
        /// 消息捕捉器
        /// </summary>
        private class LogicMsgHandler
        {
            public readonly IMsgReceiver Receiver;
            public readonly Action<object[]> Callback;
    
            public LogicMsgHandler(IMsgReceiver receiver, Action<object[]> callback)
            {
                Receiver = receiver;
                Callback = callback;
            }
        }
    
        /// <summary>
        /// 每个消息名字维护一组消息捕捉器。
        /// </summary>
        static readonly Dictionary<string, List<LogicMsgHandler>> mMsgHandlerDict =
            new Dictionary<string, List<LogicMsgHandler>>();
    
        /// <summary>
        /// 注册消息,
        /// 注意第一个参数,使用了C# this的扩展,
        /// 所以只有实现IMsgReceiver的对象才能调用此方法
        /// </summary>
        public static void RegisterLogicMsg(this IMsgReceiver self, string msgName, Action<object[]> callback)
        {
            // 略过
            if (string.IsNullOrEmpty(msgName))
            {
                Debug.LogWarning("RegisterMsg:" + msgName + " is Null or Empty");
                return;
            }
    
            // 略过
            if (null == callback)
            {
                Debug.LogWarning("RegisterMsg:" + msgName + " callback is Null");
                return;
            }
    
            // 略过
            if (!mMsgHandlerDict.ContainsKey(msgName))
            {
                mMsgHandlerDict[msgName] = new List<LogicMsgHandler>();
            }
    
            // 看下这里
            var handlers = mMsgHandlerDict[msgName];
    
            // 略过
            // 防止重复注册
            foreach (var handler in handlers)
            {
                if (handler.Receiver == self && handler.Callback == callback)
                {
                    Debug.LogWarning("RegisterMsg:" + msgName + " ayready Register");
                    return;
                }
            }
    
            // 再看下这里
            handlers.Add(new LogicMsgHandler(self, callback));
        }
    
        /// <summary>
        /// 发送消息
        /// 注意第一个参数
        /// </summary>
        public static void SendLogicMsg(this IMsgSender sender, string msgName, params object[] paramList)
        {
            // 略过,不用看
            if (string.IsNullOrEmpty(msgName))
            {
                Debug.LogWarning("SendMsg is Null or Empty");
                return;
            }
    
            // 略过,不用看
            if (!mMsgHandlerDict.ContainsKey(msgName))
            {
                Debug.LogWarning("SendMsg is UnRegister");
                return;
            }
    
            // 开始看!!!!
            var handlers = mMsgHandlerDict[msgName];
            var handlerCount = handlers.Count;
    
            // 之所以是从后向前遍历,是因为  从前向后遍历删除后索引值会不断变化
            // 参考文章,http://www.2cto.com/kf/201312/266723.html
            for (var index = handlerCount - 1; index >= 0; index--)
            {
                var handler = handlers[index];
    
                if (handler.Receiver != null)
                {
                    Debug.LogWarning("SendLogicMsg:" + msgName + " Succeed");
                    handler.Callback(paramList);
                }
                else
                {
                    handlers.Remove(handler);
                }
            }
        }
    }
    

    总结:先定义了两个空接口IMsgReceiver和IMsgSender。然后定义了LogicMsgHandler消息捕捉器,包含一个接受者IMsgReceiver和一个回调,mMsgHandlerDict作为全局的所有事件的Dictionary。通过RegisterLogicMsg注册事件,通过SendLogicMsg发送事件,遍历mMsgHandlerDict中对应事件绑定的全部回调。
    实际上是接口+接口扩展方法的用法实现了该消息机制。

    相关文章

      网友评论

          本文标题:每日一学20——凉鞋的简易消息机制

          本文链接:https://www.haomeiwen.com/subject/hrgacktx.html