美文网首页
不用转类型的事件系统(C#语言)

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

作者: SingleDigit | 来源:发表于2020-03-14 18:15 被阅读0次

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


下面直接上代码

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

相关文章

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

    其实事件系统这个东西有好多好多轮子了,我只是又自己造了一个。相比于我之前看到的一些事件系统,优点就在于不用蛋疼的转...

  • C#语言入门详解006

    006 C#类型、变量与对象详解 目录 *什么是类型*类型在C#语言中的作用*C#语言的类型系统*变量、对象与内存...

  • 浮点数的表示

    语言和C#语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据...

  • C#基础语法(二)

    四.CTS类型 C#认可的基本预定义类型并没有内置于C#语言中,而是内置于.NET Framework中。 例如,...

  • 面向对象(四)-值类型与引用类型详解

    1、C#语言中的类型 类型被分为两种:值类型(整数,bool struct char 小数)和引用类型(strin...

  • 10.18学习总结

    今天学习完了c#语言基础,包括类型转换(Parse和To string),装箱与拆箱(值类型和引用类型) ,...

  • C#语言入门详解005

    005 C#词法、类型、变量、方法与简介 目录 *构成C#语言的基本元素(标记 token)1)关键字(keywo...

  • sql注入的防护

    一、严格的数据类型 在Java,C#等高级语言中,几乎不存在数字类型注入,而对于PHP,ASP等弱类型语言,就存在...

  • 简书代码上色

    简书代码上色支持语言类型 bash | c | cpp (C++) | cs (C#) | objectivec ...

  • 【第十章】综合训练-幸运抽奖

    一、 总结 (1) . C#中运算符有算术运算符、关系运算符和逻辑运算符等(2) . C#中的类型转换分自动类型转...

网友评论

      本文标题:不用转类型的事件系统(C#语言)

      本文链接:https://www.haomeiwen.com/subject/rxbgshtx.html