C# 事件系統(三)


  前面設實現了事件系統,現在開始實現事件.我們先抽象一個事件基類.先上代碼.

    /// <summary>
    /// 事件方法
    /// </summary>
    public abstract class EventMethod
    {
        #region Field
        /// <summary>
        /// 事件句柄
        /// </summary>
        private string handle;
        #endregion

        #region Property
        /// <summary>
        /// 事件句柄
        /// </summary>
        public string Handle { get => handle; }
        #endregion

        #region Construction
        /// <summary>
        /// 創建一個 EventMethod 類新實例
        /// </summary>
        public EventMethod() => handle = GetHandle();
        #endregion

        #region Method
        /// <summary>
        /// 獲取綁定的事件句柄
        /// </summary>
        protected virtual string GetHandle() => GetType().Name;
        /// <summary>
        /// 喚醒事件
        /// </summary>
        internal abstract void Awake(params object[] parameters);
        #endregion
    }

   事件句柄就是代表了這個委托關注的哪個事件.Awake方法就是執行委托,因為事件的參數我們現在不能確定,所以這里Awake參數是params的.其他具體的事件通過重寫Awake來進行重新重構.下面就重構一個簡單按鈕單擊事件作為例子.

    /// <summary>
    /// 按鈕單擊事件
    /// </summary>
    public class BtnClick : EventMethod
    {
        #region Field
        /// <summary>
        /// 回調委托
        /// </summary>
        private Action action;
        #endregion

        #region Construction
        /// <summary>
        /// 創建一個 BtnClick 類新實例
        /// </summary>
        public BtnClick(Action action) => this.action = action;
        #endregion

        #region Method
        /// <summary>
        /// 喚醒事件
        /// </summary>
        /// <param name="parameters"></param>
        internal override void Awake(params object[] parameters) => action?.Invoke();
        #endregion
    }

  以上,我們就完成了一個事件的設計.然后補齊事件系統的觸發.

  

    /// <summary>
    /// 事件系統
    /// </summary>
    public class EventSystem
    {
        #region Field
        /// <summary>
        /// 事件容器
        /// </summary>
        private readonly Dictionary<string, HashSet<EventMethod>> events = new Dictionary<string, HashSet<EventMethod>>();
     #endregion #region Method /// <summary> /// 添加事件 /// </summary> /// <param name="eventMethod"></param> public bool Add(EventMethod eventMethod) { //事件方法集合,可能在剛判斷存在,但是在另外一個線程中同時被刪除.所以這里重試5次 for (int i = 0; i < 5; i++) { //創建時間方法集合 if (!events.ContainsKey(eventMethod.Handle)) { lock (events) { if (!events.ContainsKey(eventMethod.Handle)) events.Add(eventMethod.Handle, new HashSet<EventMethod>()); } } if (events.TryGetValue(eventMethod.Handle, out var hashSet)) { lock (hashSet) { return hashSet.Add(eventMethod); } } } return false; //throw new Exception($"添加事件{eventMethod.Handle}失敗!"); } /// <summary> /// 移除事件 /// </summary> /// <param name="eventMethod"></param> public void Remove(EventMethod eventMethod) { if (events.TryGetValue(eventMethod.Handle, out var hashSet)) { lock (hashSet) { hashSet.Remove(eventMethod); //移除已經空置的事件方法集合 if (hashSet.Count <= 0) events.Remove(eventMethod.Handle); } } } /// <summary> /// 喚醒事件 /// </summary> /// <param name="handle"></param> /// <param name="parameters"></param> public void Awake(string handle, params object[] parameters) { if (events.TryGetValue(handle, out var value)) { lock (value) { foreach (var item in value) item.Awake(parameters); } } } #endregion }

 

  通過Add/Rmove添加或移除一個委托.通過Awake方法獲取一個委托集合,然后依次調用來實現觸發這個事件.

  測試代碼如下

        static void Main(string[] args)
        {
            BtnClick btnClick = new BtnClick(() =>Console.WriteLine("按鈕被單擊"));

            EventSystem eventSystem = new EventSystem();
            eventSystem.Add(btnClick);
            eventSystem.Awake("BtnClick");

            Console.ReadLine();
        }    

  以上,我們就實現了一個簡單的事件系統.當然還有很多的可擴展部分,大家根據自己的需求調整擴展即可.

 

傳送門:

    C# 事件系統(一)

    C# 事件系統(二)

    C# 事件系統(三)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM