C#事件監聽與廣播

做用:減小代碼耦合。

1.消息類型(EventType)

public enum EventType
{
    ShowText
}
複製代碼

2. 委託,回調函數(CallBack)

  • 固然也能夠直接使用Action,Func

public delegate void CallBack();
public delegate void CallBack<T>(T arg);
public delegate void CallBack<T,X>(T arg1,X arg2);
public delegate void CallBack<T,X,Y>(T arg1,X arg2,Y arg3);
public delegate void CallBack<T,X,Y,Z>(T arg1,X arg2,Y arg3,Z arg4);
複製代碼

3. 消息處理中心(EventCenter)

using System;
using System.Collections.Generic;

public class EventCenter
{
    private static Dictionary<EventType,Delegate> m_EventTable = new Dictionary<EventType, Delegate>();
    
    //註冊監聽事件
    public static void AddListener<T>(EventType eventType, CallBack<T> callBack)
    {
        if (!m_EventTable.ContainsKey(eventType))
        {
            m_EventTable.Add(eventType, null);
        }

        Delegate d = m_EventTable[eventType];
        if (d != null && d.GetType() != callBack.GetType())
        {
            throw new Exception(string.Format("添加監聽錯誤:當前嘗試爲事件類型{0}添加不一樣的委託,本來的委託是{1},現要添加的委託是{2}", eventType,
                d.GetType(),
                callBack.GetType()));
        }
        m_EventTable[eventType] = (CallBack<T>)m_EventTable[eventType] + callBack;
    }
    
    //移除監聽事件
    public static void RemoveListener<T>(EventType eventType, CallBack<T> callBack)
    {
        if (m_EventTable.ContainsKey(eventType))
        {
            Delegate d = m_EventTable[eventType];
            if (d == null)
            {
                throw new Exception(string.Format("移除監聽錯誤:事件{0}不存在委託", eventType));
            }
            else if (d.GetType() != callBack.GetType())
            {
                throw new Exception(string.Format("移除監聽錯誤:嘗試爲事件{0}移除不一樣的委託,原先的委託爲{1},如今要移除的委託爲{2}", eventType, d.GetType(), callBack.GetType()));
            }
        }
        else
        {
            throw new Exception(string.Format("移除監聽錯誤:不存在事件{0}", eventType));
        }
        m_EventTable[eventType] = (CallBack<T>)m_EventTable[eventType] - callBack;
        if (m_EventTable[eventType] == null)
        {
            m_EventTable.Remove(eventType);
        }
    }
    
    //廣播事件
    public static void Broadcast<T>(EventType eventType,T arg)
    {
        Delegate d;
        if (m_EventTable.TryGetValue(eventType, out d))
        {
            CallBack<T> callBack = d as CallBack<T>;
            if (callBack != null)
            {
                callBack(arg);
            }
            else
            {
                throw new Exception(string.Format("事件廣播錯誤:事件{0}存在不一樣的委託類型", eventType));
            }
        }
    }
}
複製代碼

使用這個系統,實現一個按鈕按下,顯示文本信息

  • 在一個Text對象上掛載一個ShowText.cs的腳本,腳本以下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ShowText : MonoBehaviour
{
    void Awake()
    {
        EventCenter.AddListener<string>(EventType.ShowText,Show);
    }

    void OnDestory()
    {
        EventCenter.RemoveListener<string>(EventType.ShowText,Show);
    }

    public void Show(string str)
    {
        this.gameObject.GetComponent<Text>().text = str;
    }
}
複製代碼

  • 在一個Button對象上掛載一個BtnClick.cs腳本,腳本以下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BtnClick : MonoBehaviour
{
	// Use this for initialization
	void Start ()
	{
	    this.GetComponent<Button>().onClick.AddListener(() => { EventCenter.Broadcast(EventType.ShowText,"被點擊了"); });
    }
}複製代碼


倉庫代碼:https://gitee.com/hankangwen/EventBroadcastSystem
相關文章
相關標籤/搜索