事件系统

一、 委托与事件

1.1 委托

delegate是一个关键字,用来声明委托类型,Delegate是一个类,是委托类型的基类,但只有系统和编辑器可以显示地从Delegate类或者MulticastDelegate类派生,通常我们使用delegate关键字来定义委托类型。

委托是一种引用类型(类似于函数指针),允许我们封装方法的引用,通过使用委托,我们可以将方法作为参数传递给其他方法,或者将方法类型组合在一起,从而实现更加灵活地编程。

1.2 事件

事件是一种特殊的委托实例化,用于外部接口,事件基于委托而并非委托,可以看成委托的代理,外部类只能通过+=-=来注册和注销事件,而不能主动触发事件。

1.3 委托与事件的区别

  1. 事件是对委托的包装,保护了委托字段,对外不开放,只提供添加和移除事件的方法。
  2. 事件的触发是在对象的内部。
  3. 事件是一种更安全、更易用的方式来处理回调。

二、事件系统

  • EventManager: 事件管理系统类, 包括了注册、注销、广播事件, 其中能够监听5个以内的事件
using LFrameWork;
using System;
using System.Collections.Generic;

namespace Client.Event
{
    public class EventManager
    {
        private Dictionary<EventType, Delegate> _eventTable;
        protected override void OnInit()
        {
            _eventTable = new Dictionary<EventType, Delegate>();
        }

        private void OnListenerAdding(EventType eventType, Delegate action)
        {
            if (!_eventTable.ContainsKey(eventType)) 
            {
                _eventTable.Add(eventType, null);
            }
            Delegate @delegate = _eventTable[eventType];
            if (@delegate != null && @delegate.GetType() != action.GetType())
            {
                GameLogger.LogError($"事件添加的类型不同, {eventType} DelagateType{@delegate.GetType()} actionType {action.GetType()}");
            }
        }

        public void RegisterEvent(EventType eventType, CallBack action) 
        {
            OnListenerAdding(eventType, action);
            if (_eventTable.TryGetValue(eventType, out var @delegate))
            {
                _eventTable[eventType] = (CallBack)@delegate + action;
            }
        }

        public void RegisterEvent<T>(EventType eventType, CallBack<T> action)
        {
            OnListenerAdding(eventType, action);
            if (_eventTable.TryGetValue(eventType, out var @delegate))
            {
                _eventTable[eventType] = (CallBack<T>)@delegate + action;
            }
        }

        public void RegisterEvent<T, X>(EventType eventType, CallBack<T, X> action)
        {
            OnListenerAdding(eventType, action);
            if (_eventTable.TryGetValue(eventType, out var @delegate))
            {
                _eventTable[eventType] = (CallBack<T, X>)@delegate + action;
            }
        }

        public void RegisterEvent<T, X, Y>(EventType eventType, CallBack<T, X, Y> action)
        {
            OnListenerAdding(eventType, action);
            if (_eventTable.TryGetValue(eventType, out var @delegate))
            {
                _eventTable[eventType] = (CallBack<T, X, Y>)@delegate + action;
            }
        }

        public void RegisterEvent<T, X, Y, Z>(EventType eventType, CallBack<T, X, Y, Z> action)
        {
            OnListenerAdding(eventType, action);
            if (_eventTable.TryGetValue(eventType, out var @delegate))
            {
                _eventTable[eventType] = (CallBack<T, X, Y, Z>)@delegate + action;
            }
        }

        public void RegisterEvent<T, X, Y, Z,W>(EventType eventType, CallBack<T, X, Y, Z,W> action)
        {
            OnListenerAdding(eventType, action);
            if (_eventTable.TryGetValue(eventType, out var @delegate))
            {
                _eventTable[eventType] = (CallBack<T, X, Y, Z, W>)@delegate + action;
            }
        }

        private void OnListenerRemoving(EventType eventType, Delegate callBack)
        {
            if (_eventTable.ContainsKey(eventType))
            {
                Delegate @delegate = _eventTable[eventType];
                if (@delegate == null)
                {
                    GameLogger.LogError($"移除监听错误: 事件{eventType}没有对应的委托");
                }
                else if (@delegate.GetType() != callBack.GetType())
                {
                    GameLogger.LogError($"移除监听错误: 尝试为事件{eventType}移除不同类型的委托,当前委托类型为{@delegate.GetType()},要移除的类型为{callBack.GetType()}");
                }
                else
                {
                    GameLogger.LogError($"移除监听错误: 没有事件码 {eventType}");
                }
            }
        }

        private void OnListenerRemoved(EventType eventType)
        {
            if (_eventTable[eventType] == null) _eventTable.Remove(eventType);
        }

        public void UnRegisterEvent(EventType eventType, CallBack callBack) 
        {
            OnListenerRemoving(eventType, callBack);
            _eventTable[eventType] = (CallBack)_eventTable[eventType] - callBack;
            OnListenerRemoved(eventType);
        }

        public void UnRegisterEvent<T>(EventType eventType, CallBack<T> callBack)
        {
            OnListenerRemoving(eventType, callBack);
            _eventTable[eventType] = (CallBack<T>)_eventTable[eventType] - callBack;
            OnListenerRemoved(eventType);
        }

        public void UnRegisterEvent<T, X>(EventType eventType, CallBack<T, X> callBack)
        {
            OnListenerRemoving(eventType, callBack);
            _eventTable[eventType] = (CallBack<T, X>)_eventTable[eventType] - callBack;
            OnListenerRemoved(eventType);
        }

        public void UnRegisterEvent<T, X, Y>(EventType eventType, CallBack<T, X, Y> callBack)
        {
            OnListenerRemoving(eventType, callBack);
            _eventTable[eventType] = (CallBack<T, X, Y>)_eventTable[eventType] - callBack;
            OnListenerRemoved(eventType);
        }

        public void UnRegisterEvent<T, X, Y, Z>(EventType eventType, CallBack<T, X, Y, Z> callBack)
        {
            OnListenerRemoving(eventType, callBack);
            _eventTable[eventType] = (CallBack<T, X, Y, Z>)_eventTable[eventType] - callBack;
            OnListenerRemoved(eventType);
        }

        public void UnRegisterEvent<T, X, Y, Z, W>(EventType eventType, CallBack<T, X, Y, Z, W> callBack)
        {
            OnListenerRemoving(eventType, callBack);
            _eventTable[eventType] = (CallBack<T, X, Y, Z, W>)_eventTable[eventType] - callBack;
            OnListenerRemoved(eventType);
        }

        public void BroadCast(EventType eventType)
        {
            try
            {
                if (_eventTable.TryGetValue(eventType, out var @delegate))
                {
                    CallBack callBack = @delegate as CallBack;
                    callBack?.Invoke();
                }
            }
            catch
            {
                GameLogger.LogError($"BroadCast EventType {eventType} error");
            }

        }
        public void BroadCast<T>(EventType eventType, T arg)
        {
            try
            {
                if (_eventTable.TryGetValue(eventType, out var @delegate))
                {
                    CallBack<T> callBack = @delegate as CallBack<T>;
                    callBack?.Invoke(arg);
                }
            }
            catch
            {
                GameLogger.LogError($"BroadCast EventType {eventType} error");
            }
        }

        public void BroadCast<T, X>(EventType eventType, T arg1, X arg2)
        {
            try
            {
                if (_eventTable.TryGetValue(eventType, out var @delegate))
                {
                    CallBack<T, X> callBack = @delegate as CallBack<T, X>;
                    callBack?.Invoke(arg1, arg2);
                }
            }
            catch
            {
                GameLogger.LogError($"BroadCast EventType {eventType} error");
            }
        }

        public void BroadCast<T, X, Y>(EventType eventType, T arg1, X arg2, Y arg3)
        {
            try
            {
                if (_eventTable.TryGetValue(eventType, out var @delegate))
                {
                    CallBack<T, X, Y> callBack = @delegate as CallBack<T, X, Y>;
                    callBack?.Invoke(arg1, arg2, arg3);
                }
            }
            catch
            {
                GameLogger.LogError($"BroadCast EventType {eventType} error");
            }
        }

        public void BroadCast<T, X, Y, Z>(EventType eventType, T arg1, X arg2, Y arg3, Z arg4)
        {
            try
            {
                if (_eventTable.TryGetValue(eventType, out var @delegate))
                {
                    CallBack<T, X, Y, Z> callBack = @delegate as CallBack<T, X, Y, Z>;
                    callBack?.Invoke(arg1, arg2, arg3, arg4);
                }
            }
            catch
            {
                GameLogger.LogError($"BroadCast EventType {eventType} error");
            }
        }

        public void BroadCast<T, X, Y, Z, W>(EventType eventType, T arg1, X arg2, Y arg3, Z arg4, W arg5)
        {
            try
            {
                if (_eventTable.TryGetValue(eventType, out var @delegate))
                {
                    CallBack<T, X, Y, Z, W> callBack = @delegate as CallBack<T, X, Y, Z, W>;
                    callBack?.Invoke(arg1, arg2, arg3, arg4, arg5);
                }
            }
            catch
            {
                GameLogger.LogError($"BroadCast EventType {eventType} error");
            }
        }

        protected override void OnRelease()
        {
            _eventTable.Clear();
        }
    }
}
  • EventType: 事件系统类型(枚举值)

    namespace Client.Event
    {
      public enum EventType
      {
          Main,
      }
    }
  • CallBack: 事件委托类型

    namespace Client.Event
    {
      public delegate void CallBack();
      public delegate void CallBack(T arg);
      public delegate void CallBack(T arg1, X arg2);
      public delegate void CallBack(T arg1, X arg2, Y arg3);
      public delegate void CallBack(T arg1, X arg2, Y arg3, Z arg4);
      public delegate void CallBack(T arg1, X arg2, Y arg3, Z arg4, W arg5);
    
    }