不用转类型的事件系统(C#语言)

2020-03-14  本文已影响0人  SingleDigit

其实事件系统这个东西有好多好多轮子了,我只是又自己造了一个。
相比于我之前看到的一些事件系统,优点就在于不用蛋疼的转类型吧。
不足之处,还希望大佬能够指点。


下面直接上代码

using System.Collections.Generic;

namespace SFw.Core
{
    /// <summary>
    /// 事件处理委托
    /// </summary>
    /// <param name="args">事件参数</param>
    /// <typeparam name="T">事件类型</typeparam>
    public delegate void EventHandler<in T>(T args) where T : Event<T>;

    /// <summary>
    /// 事件接口
    /// </summary>
    public interface IEvent//为了解决EventCrossThreadHelper中事件数据的存储
    {
        /// <summary>
        /// 事件发送者
        /// </summary>
        object Sender { get; set; }

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="sender">传参自动修改Sender</param>
        void Trigger(object sender = null);
    }

    /// <summary>
    /// 事件基类
    /// </summary>
    /// <typeparam name="T">事件类型</typeparam>
    public abstract partial class Event<T> : IEvent where T : Event<T>, IEvent
    {
        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="sender">传参自动修改Sender</param>
        public void Trigger(object sender = null)
        {
            Sender = sender ?? Sender;
            Trigger((T)this);
        }

        /// <summary>
        /// 事件发送方
        /// </summary>
        public object Sender { get; set; }
    }

    /// <summary>
    /// 事件管理类
    /// </summary>
    /// <typeparam name="T">事件类型</typeparam>
    public partial class Event<T> : IEvent where T : Event<T>, IEvent
    {
        /// <summary>
        /// 添加事件
        /// </summary>
        /// <param name="eventHandler"></param>
        public static void Add(EventHandler<T> eventHandler)
        { 
            _event += eventHandler;
        }

        /// <summary>
        /// 移除事件
        /// </summary>
        /// <param name="eventHandler"></param>
        public static void Remove(EventHandler<T> eventHandler)
        {
            _event -= eventHandler;
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="args"></param>
        public static void Trigger(T args = default)
        {
            _event?.Invoke(args);
        }

        /// <summary>
        /// 支线程想主线程触发事件:主要是为了解决网络部分数据处理的问题
        /// </summary>
        /// <param name="args"></param>
        public static void JumpTrigger(T args = default)
        {
            EventCrossThreadHelper.AddEvent(args);
        }
        private static event EventHandler<T> _event; 
    }

    /// <summary>
    /// 跨线程触发事件辅助类(主要用于将网络/串口数据同步到主线程)
    /// </summary>
    public class EventCrossThreadHelper
    {
        /// <summary>
        /// 主线程需要循环调用此方法
        /// </summary>
        public static void MainThreadUpdate()
        {
            if (_eventQueue.Count > 0)
            {
                lock (_lockHelper)
                {
                    int count = 0;
                    while (_eventQueue.Count > 0 && count < MaxHandleCount)
                    {
                        _eventQueue.Dequeue()?.Trigger();
                        count++;
                    }   
                }
            }
        }

        /// <summary>
        /// 添加事件
        /// </summary>
        /// <param name="eventArg"></param>
        public static void AddEvent(IEvent eventArg)
        {
            lock (_lockHelper)
            {
                _eventQueue.Enqueue(eventArg);
            }
        }

        /// <summary>
        /// 每一帧处理事件的最大数量
        /// </summary>
        public static int MaxHandleCount = 30;
        
        static Queue<IEvent> _eventQueue = new Queue<IEvent>(); 
        static object _lockHelper = new object();
    }
}
using SFw.Core;
using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        EventTest.Add(Handler);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            EventTest.Trigger();//触发方式1
            
            var args = new EventTest {Count = 10};
            
            EventTest.Trigger(args);//触发方式2
            args.Trigger();//触发方式3
            
            var sender = new object();
            args.Trigger(sender);//触发方式4
        }
    }
    
    private void Handler(EventTest args)
    {
        Debug.Log(args);
        Debug.Log(args?.Sender);
        Debug.Log(args?.Count);
    }
}


ps. 之所以搞这个东西出来,是因为写事件相关的代码时,总是要蛋疼的转类型,实在感觉有些烦。不足之处,还请各位大佬指正。

上一篇 下一篇

猜你喜欢

热点阅读