TEngine框架的事件系统

事件系统对于游戏项目来说是必不可少的系统模块,它能够有效地降低代码的耦合度。

using System;
using System.Collections.Generic;

namespace TEngine.Runtime
{
    /// <summary>
    /// 事件数据
    /// </summary>
    class DEventDelegateData
    {
        /// <summary>
        /// 事件ID
        /// </summary>
        private int m_eventType = 0;
        /// <summary>
        /// 该事件所有的委托回调列表
        /// </summary>
        public List<Delegate> m_listExist = new List<Delegate>();
        /// <summary>
        /// 待新增的回调列表
        /// </summary>
        private List<Delegate> m_addList = new List<Delegate>();
        /// <summary>
        /// 待移除的回调列表
        /// </summary>
        private List<Delegate> m_deleteList = new List<Delegate>();

        /// <summary>
        /// 是否在执行回调中
        /// </summary>
        private bool m_isExcute = false;

        /// <summary>
        /// 是否已经脏了
        /// </summary>
        private bool m_dirty = false;

        public DEventDelegateData(int evnetType)
        {
            m_eventType = evnetType;
        }


        /// <summary>
        /// 添加事件回调
        /// </summary>
        /// <param name="handler"></param>
        /// <returns></returns>
        public bool AddHandler(Delegate handler)
        {
            if (m_listExist.Contains(handler))
            {
                Log.Fatal("Repeated Add Handler");
                return false;
            }

            if (m_isExcute)
            {
                m_dirty = true;
                m_addList.Add(handler);
            }
            else
            {
                m_listExist.Add(handler);
            }

            return true;
        }


        /// <summary>
        /// 移除事件回调
        /// </summary>
        /// <param name="hander"></param>
        public void RmvHandler(Delegate hander)
        {
            if (m_isExcute)
            {
                m_dirty = true;
                m_deleteList.Add(hander);
            }
            else
            {
                if (!m_listExist.Remove(hander))
                {
                    Log.Fatal("Delete handle failed, not exist, EventId: {0}", StringId.HashToString(m_eventType));
                }
            }
        }


        /// <summary>
        /// 检查事件的委托回调是否发生了修改,如果有,则把新增的加入、待移除的除掉
        /// </summary>
        private void CheckModify()
        {
            m_isExcute = false;
            if (m_dirty)
            {
                for (int i = 0; i < m_addList.Count; i++)
                {
                    m_listExist.Add(m_addList[i]);
                }

                m_addList.Clear();

                for (int i = 0; i < m_deleteList.Count; i++)
                {
                    m_listExist.Remove(m_deleteList[i]);
                }

                m_deleteList.Clear();
            }
        }


        /// <summary>
        /// 执行回调【无参数】
        /// </summary>
        public void Callback()
        {
            m_isExcute = true;
            for (var i = 0; i < m_listExist.Count; i++)
            {
                var d = m_listExist[i];
                Action action = d as Action;
                if (action != null)
                {
                    action();
                }
            }

            CheckModify();
        }

        /// <summary>
        /// 执行回调【一个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="arg1">参数</param>
        public void Callback<T>(T arg1)
        {
            m_isExcute = true;
            for (var i = 0; i < m_listExist.Count; i++)
            {
                var d = m_listExist[i];
                var action = d as Action<T>;
                if (action != null)
                {
                    action(arg1);
                }
            }

            CheckModify();
        }

        /// <summary>
        /// 执行回调【2个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        public void Callback<T, U>(T arg1, U arg2)
        {
            m_isExcute = true;
            for (var i = 0; i < m_listExist.Count; i++)
            {
                var d = m_listExist[i];
                var action = d as Action<T, U>;
                if (action != null)
                {
                    action(arg1, arg2);
                }
            }

            CheckModify();
        }


        /// <summary>
        /// 执行回调【3个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        /// <param name="arg3">参数3</param>
        public void Callback<T, U, V>(T arg1, U arg2, V arg3)
        {
            m_isExcute = true;
            for (var i = 0; i < m_listExist.Count; i++)
            {
                var d = m_listExist[i];
                var action = d as Action<T, U, V>;
                if (action != null)
                {
                    action(arg1, arg2, arg3);
                }
            }

            CheckModify();
        }


        /// <summary>
        /// 执行回调【4个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="W"></typeparam>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        /// <param name="arg3">参数3</param>
        /// <param name="arg4">参数4</param>
        public void Callback<T, U, V, W>(T arg1, U arg2, V arg3, W arg4)
        {
            m_isExcute = true;
            for (var i = 0; i < m_listExist.Count; i++)
            {
                var d = m_listExist[i];
                var action = d as Action<T, U, V, W>;
                if (action != null)
                {
                    action(arg1, arg2, arg3, arg4);
                }
            }

            CheckModify();
        }


        /// <summary>
        /// 执行回调【5个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="W"></typeparam>
        /// <typeparam name="X"></typeparam>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        /// <param name="arg3">参数3</param>
        /// <param name="arg4">参数4</param>
        /// <param name="arg5">参数5</param>
        public void Callback<T, U, V, W, X>(T arg1, U arg2, V arg3, W arg4, X arg5)
        {
            m_isExcute = true;
            for (var i = 0; i < m_listExist.Count; i++)
            {
                var d = m_listExist[i];
                var action = d as Action<T, U, V, W, X>;
                if (action != null)
                {
                    action(arg1, arg2, arg3, arg4, arg5);
                }
            }

            CheckModify();
        }
    }

    /// <summary>
    /// 事件注册分发器
    /// </summary>
    class DEventDispatcher
    {

        /// <summary>
        /// 事件字典列表
        /// </summary>
        static Dictionary<int, DEventDelegateData> m_eventTable = new Dictionary<int, DEventDelegateData>();

        #region 事件管理接口

        /// <summary>
        /// 添加事件监听
        /// </summary>
        /// <param name="eventType">事件ID</param>
        /// <param name="handler">回调</param>
        /// <returns></returns>
        public bool AddEventListener(int eventType, Delegate handler)
        {
            DEventDelegateData data;
            if (!m_eventTable.TryGetValue(eventType, out data))
            {
                data = new DEventDelegateData(eventType);
                m_eventTable.Add(eventType, data);
            }

            return data.AddHandler(handler);
        }


        /// <summary>
        /// 注销事件回调
        /// </summary>
        /// <param name="eventType"></param>
        /// <param name="handler"></param>
        public void RemoveEventListener(int eventType, Delegate handler)
        {
            DEventDelegateData data;
            if (m_eventTable.TryGetValue(eventType, out data))
            {
                data.RmvHandler(handler);
            }
        }

        #endregion

        #region 事件分发接口

        /// <summary>
        /// 事件发送【无参数】
        /// </summary>
        /// <param name="eventType">事件ID</param>
        public void Send(int eventType)
        {
            DEventDelegateData d;
            if (m_eventTable.TryGetValue(eventType, out d))
            {
                d.Callback();
            }
        }

        /// <summary>
        /// 事件发送【1个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="eventType">事件ID</param>
        /// <param name="arg1">参数1</param>
        public void Send<T>(int eventType, T arg1)
        {
            DEventDelegateData d;
            if (m_eventTable.TryGetValue(eventType, out d))
            {
                d.Callback(arg1);
            }
        }

        /// <summary>
        /// 事件发送【2个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <param name="eventType">事件ID</param>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        public void Send<T, U>(int eventType, T arg1, U arg2)
        {
            DEventDelegateData d;
            if (m_eventTable.TryGetValue(eventType, out d))
            {
                d.Callback(arg1, arg2);
            }
        }

        /// <summary>
        /// 事件发送【3个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <param name="eventType">事件ID</param>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        /// <param name="arg3">参数3</param>
        public void Send<T, U, V>(int eventType, T arg1, U arg2, V arg3)
        {
            DEventDelegateData d;
            if (m_eventTable.TryGetValue(eventType, out d))
            {
                d.Callback(arg1, arg2, arg3);
            }
        }

        /// <summary>
        /// 事件发送【4个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="W"></typeparam>
        /// <param name="eventType">事件ID</param>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        /// <param name="arg3">参数3</param>
        /// <param name="arg4">参数4</param>
        public void Send<T, U, V, W>(int eventType, T arg1, U arg2, V arg3, W arg4)
        {
            DEventDelegateData d;
            if (m_eventTable.TryGetValue(eventType, out d))
            {
                d.Callback(arg1, arg2, arg3, arg4);
            }
        }

        /// <summary>
        /// 事件发送【5个参数】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="W"></typeparam>
        /// <typeparam name="X"></typeparam>
        /// <param name="eventType">事件ID</param>
        /// <param name="arg1">参数1</param>
        /// <param name="arg2">参数2</param>
        /// <param name="arg3">参数3</param>
        /// <param name="arg4">参数4</param>
        /// <param name="arg5">参数5</param>
        public void Send<T, U, V, W, X>(int eventType, T arg1, U arg2, V arg3, W arg4, X arg5)
        {
            DEventDelegateData d;
            if (m_eventTable.TryGetValue(eventType, out d))
            {
                d.Callback(arg1, arg2, arg3, arg4, arg5);
            }
        }

        #endregion
    }
}

上面是包含事件的注册、注销以及事件的分发等接口的封装。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Data菌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值