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

学习来源: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
{
    /// 
    /// 消息捕捉器
    /// 
    private class LogicMsgHandler
    {
        public readonly IMsgReceiver Receiver;
        public readonly Action Callback;

        public LogicMsgHandler(IMsgReceiver receiver, Action callback)
        {
            Receiver = receiver;
            Callback = callback;
        }
    }

    /// 
    /// 每个消息名字维护一组消息捕捉器。
    /// 
    static readonly Dictionary> mMsgHandlerDict =
        new Dictionary>();

    /// 
    /// 注册消息,
    /// 注意第一个参数,使用了C# this的扩展,
    /// 所以只有实现IMsgReceiver的对象才能调用此方法
    /// 
    public static void RegisterLogicMsg(this IMsgReceiver self, string msgName, Action 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();
        }

        // 看下这里
        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));
    }

    /// 
    /// 发送消息
    /// 注意第一个参数
    /// 
    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——凉鞋的简易消息机制)