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
相关文章
相关标签/搜索