功能:通过全局事件使类与类之间的通信解耦(两个类之间无需知道彼此的存在,类似广播电台,一个类发送,一个类监听)。
特点:使一个类继承Ib_Event即可快速声明一个全局同步事件,支持立即/延迟一帧调用、同步/异步执行、重载了至多五个参数的传入。
性能:在事件注册和注销时会有容器容量变化产生的GC。通过List和脏标记,大量相同事件在同一帧内同时注册或注销会有多次List扩容和一次数组复制扩容带来的GC(在注册后第一次调用时产生),后续调用事件不会产生GC。
可能的缺点:不引用Ib_Event所在程序集的话,无法跨程序集调用。要十分注意事件的注册和注销,尤其是场景切换的时候,不然会内存泄漏。
更新记录:
2025-12-14 v0.3 优化了n个相同事件在同一帧同时注册/注销时,会进行n次数组复制扩容的性能问题。现在每次注册/注销只会List进行扩容,产生微量GC,并在注册后的首次调用时将List转化为数组(n次同时注册只会产生一次数组的扩容)。对异步事件中心进行优化。
2025-12-23 v0.4 使用Ib_Event.InvokeNextFrame()延迟一帧调用事件时,每次都会为Ib_Async.DelayDoSomething()方法传入新的委托实例产生GC。现在使用了一个只读静态委托变量CachedInvokeAction缓存,避免了每次调用的GC。
public abstract partial class Ib_Event<T, T1, T2> : IIb_Event where T : Ib_Event<T, T1, T2>
{
private static readonly Action<T1, T2> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, cts);
}
示例:我挂了,使游戏结束。
玩家类:在挂了以后发送OnPlayerDead事件。
//一个类继承Ib_Event,即可新建一个全局事件。这个类不需要任何成员。
public class OnPlayerDead : Ib_Event<OnPlayerDead> { }
public class Sample_Ib_Event_Player : MonoBehaviour
{
void Start()
{
//我在五秒后挂了
Ib_Async.DelayDoSomething(5,Die,this.GetCancellationTokenOnDestroy());
}
void Die()
{
Ib_Log.Info($"{GetType().Name} >> 啊,我挂了。");
//发送我挂了的消息
OnPlayerDead.Invoke();
}
}
管理器:监听OnPlayerDead事件,触发后调用GameOver()结束游戏。
//游戏进程的管理器,可以在这里接收玩家挂了的消息。
public class Sample_Ib_Event_GameManager : Ib_Singleton<Sample_Ib_Event_GameManager>
{
protected override void Awake()
{
base.Awake();
//订阅玩家挂了的事件,如果消息传来,就调用GameOver()方法使游戏结束。
OnPlayerDead.Register(GameOver);
}
protected override void OnDestroy()
{
base.OnDestroy();
//(必须)在生命周期的末尾取消订阅事件,避免内存泄漏。
OnPlayerDead.Deregister(GameOver);
}
//如果玩家挂了,就游戏结束
void GameOver()
{
Ib_Log.Info($"{GetType().Name} >> 玩家挂了,游戏结束");
}
}

玩家类和管理器类之间并没有任何的相互引用,它们不知道彼此的存在,它们的通信全都由第三方的事件中心来进行接收和转发。这样这两个之间就没有了耦合关系,哪怕管理器类不存在,也不有任何的报错。
Ib_Event也支持参数的传递,如玩家挂了,我需要传递玩家挂了的消息和遗言。管理器的GameOver方法就需要接收传来的string类型遗言,并进行打印。
//一个类继承Ib_Event,即可就新建一个全局事件。这个类不需要任何成员。
public class OnPlayerDead : Ib_Event<OnPlayerDead,string> { }
public class Sample_Ib_Event_Player : MonoBehaviour
{
void Start()
{
//我在五秒后挂了
Ib_Async.DelayDoSomething(5,Die,this.GetCancellationTokenOnDestroy());
}
void Die()
{
Ib_Log.Info($"{GetType().Name} >> 啊,我挂了。");
//发送我挂了的消息
OnPlayerDead.Invoke("卧槽,我竟然挂了,我不甘心啊");
}
}
//如果玩家挂了,就游戏结束
void GameOver(string message)
{
Ib_Log.Info($"遗言 >> {message}");
Ib_Log.Info($"{GetType().Name} >> 玩家挂了,游戏结束");
}

核心功能简易实现:
using System;
using System.Collections.Generic;
/// <summary>
/// 事件系统的基础接口(标记接口)。
/// <para>主要用于泛型约束,确保只有实现了该接口的类型才能被注册到事件中心。</para>
/// </summary>
public interface ISample_Ib_Event { }
/// <summary>
/// 事件基类。所有自定义事件需继承此类。使用示例:public class 事件名 : Sample_Ib_Event<事件名> { }
/// <para>使用 CRTP (Curiously Recurring Template Pattern) 模式,简化静态调用。</para>
/// </summary>
/// <typeparam name="T">具体的事件类型(即子类自身)。</typeparam>
public abstract class Sample_Ib_Event<T> : ISample_Ib_Event where T : Sample_Ib_Event<T>
{
/// <summary>
/// 触发(广播)事件。
/// <para>通知所有订阅了该事件的监听者。</para>
/// </summary>
public static void Invoke()
{
Sample_Ib_EventHandler.Invoke<T>();
}
/// <summary>
/// 注册(订阅)事件。
/// </summary>
/// <param name="action">事件触发时要执行的回调函数。</param>
public static void Register(Action action)
{
Sample_Ib_EventHandler.Register<T>(action);
}
/// <summary>
/// 取消注册(退订)事件。
/// <para>注意:必须传入与注册时完全相同的委托实例。</para>
/// </summary>
/// <param name="action">需要移除的回调函数。</param>
public static void Deregister(Action action)
{
Sample_Ib_EventHandler.Deregister<T>(action);
}
}
/// <summary>
/// 事件中心(核心管理器)。
/// <para>负责底层存储和分发消息。通常不需要直接调用此类,而是通过继承 <see cref="Sample_Ib_Event{T}"/> 来使用。</para>
/// </summary>
public static class Sample_Ib_EventHandler
{
// 存储所有事件委托的字典,Key 为事件类型,Value 为多播委托
private static readonly Dictionary<Type, Action> EventsDict = new();
/// <summary>
/// 执行指定类型的事件。
/// </summary>
/// <typeparam name="T">必须实现 <see cref="ISample_Ib_Event"/> 的事件类型。</typeparam>
public static void Invoke<T>() where T : ISample_Ib_Event
{
if (EventsDict.TryGetValue(typeof(T), out var action))
{
action?.Invoke();
}
}
/// <summary>
/// 将回调注册到指定类型的事件中。
/// </summary>
/// <typeparam name="T">事件类型。</typeparam>
/// <param name="action">回调委托。</param>
public static void Register<T>(Action action) where T : ISample_Ib_Event
{
Type eventType = typeof(T);
// 如果字典中不存在该 Key,则添加;如果存在,则使用 += 进行多播委托叠加
if (!EventsDict.TryAdd(eventType, action))
EventsDict[eventType] += action;
}
/// <summary>
/// 从指定类型的事件中移除回调。
/// </summary>
/// <typeparam name="T">事件类型。</typeparam>
/// <param name="action">要移除的回调委托。</param>
public static void Deregister<T>(Action action) where T : ISample_Ib_Event
{
Type eventType = typeof(T);
if (EventsDict.ContainsKey(eventType))
{
EventsDict[eventType] -= action;
}
}
}
同步事件中心源码:
*调用事件Invoke()不会产生GC
*注册事件Register()和取消事件Deregister()会有数组元素的复制,会有GC,但理论这是低频率操作,因此没有太大影响,若需要频繁注册与取消,请注意。

//支持至多五个参数的事件中心。
//使用方法:
//1、声明一个事件类,继承Ib_Event
// public class OnGameLog : Ib_Event<OnGameLog,string> { };
//2、在Mono类中进行注册与注销
// Action<string> testAction = (string content)=>Ib_Log.Info(content);
// OnGameLog.Register(testAction);
// OnGameLog.Deregister(testAction);
//3、调用
//OnGameLog.Invoke("成功调用");
namespace Ib_Core
{
using System;
using System.Collections.Generic;
internal interface IIb_Event
{
}
#region 无参数事件基类
public abstract partial class Ib_Event<T> : IIb_Event where T : Ib_Event<T>
{
public static void Invoke() => Ib_EventHandler.Invoke<T>();
public static void Register(Action action) => Ib_EventHandler.Register<T>(action);
public static void Deregister(Action action) => Ib_EventHandler.Deregister<T>(action);
}
#endregion
#region 单参数事件基类
public abstract partial class Ib_Event<T, T1> : IIb_Event where T : Ib_Event<T, T1>
{
public static void Invoke(T1 arg1) => Ib_EventHandler.Invoke<T, T1>(arg1);
public static void Register(Action<T1> action) => Ib_EventHandler.Register<T, T1>(action);
public static void Deregister(Action<T1> action) => Ib_EventHandler.Deregister<T, T1>(action);
}
#endregion
#region 双参数事件基类
public abstract partial class Ib_Event<T, T1, T2> : IIb_Event where T : Ib_Event<T, T1, T2>
{
public static void Invoke(T1 arg1, T2 arg2) => Ib_EventHandler.Invoke<T, T1, T2>(arg1, arg2);
public static void Register(Action<T1, T2> action) => Ib_EventHandler.Register<T, T1, T2>(action);
public static void Deregister(Action<T1, T2> action) => Ib_EventHandler.Deregister<T, T1, T2>(action);
}
#endregion
#region 三参数事件基类
public abstract partial class Ib_Event<T, T1, T2, T3> : IIb_Event where T : Ib_Event<T, T1, T2, T3>
{
public static void Invoke(T1 arg1, T2 arg2, T3 arg3) => Ib_EventHandler.Invoke<T, T1, T2, T3>(arg1, arg2, arg3);
public static void Register(Action<T1, T2, T3> action) => Ib_EventHandler.Register<T, T1, T2, T3>(action);
public static void Deregister(Action<T1, T2, T3> action) => Ib_EventHandler.Deregister<T, T1, T2, T3>(action);
}
#endregion
#region 四参数事件基类
public abstract partial class Ib_Event<T, T1, T2, T3, T4> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4>
{
public static void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4) =>
Ib_EventHandler.Invoke<T, T1, T2, T3, T4>(arg1, arg2, arg3, arg4);
public static void Register(Action<T1, T2, T3, T4> action) =>
Ib_EventHandler.Register<T, T1, T2, T3, T4>(action);
public static void Deregister(Action<T1, T2, T3, T4> action) =>
Ib_EventHandler.Deregister<T, T1, T2, T3, T4>(action);
}
#endregion
#region 五参数事件基类
public abstract partial class Ib_Event<T, T1, T2, T3, T4, T5> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4, T5>
{
public static void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) =>
Ib_EventHandler.Invoke<T, T1, T2, T3, T4, T5>(arg1, arg2, arg3, arg4, arg5);
public static void Register(Action<T1, T2, T3, T4, T5> action) =>
Ib_EventHandler.Register<T, T1, T2, T3, T4, T5>(action);
public static void Deregister(Action<T1, T2, T3, T4, T5> action) =>
Ib_EventHandler.Deregister<T, T1, T2, T3, T4, T5>(action);
}
#endregion
#region 事件容器
/// <summary>
/// 事件容器,使用写时复制(Copy-on-Write)策略来实现 0 GC 的 Invoke
/// </summary>
internal class Ib_EventContainer
{
// 直接持有数组,Invoke时直接遍历这个数组
private Delegate[] _actionArray = Array.Empty<Delegate>();
public bool IsEmpty => _actionList.Count == 0;
//list和脏标记用于防止同一帧内有大量事件同时注册,导致卡顿
private readonly List<Delegate> _actionList = new List<Delegate>();
private bool _isDirty = false;//脏标记
public void Add(Delegate callback)
{
if (callback == null) return;
_actionList.Add(callback);
_isDirty = true;
}
public void Remove(Delegate callback)
{
if (callback == null) return;
if (_actionList.Remove(callback))
{
_isDirty = true;
}
}
public Delegate[] GetDelegateArray()
{
if (_isDirty)
{
_actionArray = _actionList.ToArray();
_isDirty = false;
}
return _actionArray;
}
}
#endregion
internal static partial class Ib_EventHandler
{
private static readonly Dictionary<Type, Ib_EventContainer> EventsDict = new();
private static readonly object _lock = new object();
// 获取或创建容器的辅助方法
private static Ib_EventContainer GetContainer(Type type, bool createIfNull)
{
if (!EventsDict.TryGetValue(type, out var container))
{
if (createIfNull)
{
container = new Ib_EventContainer();
EventsDict[type] = container;
}
}
return container;
}
#region 无参数的事件处理
public static void Invoke<T>() where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action)actions[i];
try
{
action?.Invoke();
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T>(Action action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T>(Action action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 单参数的事件处理
public static void Invoke<T, T1>(T1 arg1) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1>)actions[i];
try
{
action?.Invoke(arg1);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1>(Action<T1> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1>(Action<T1> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 双参数的事件处理
public static void Invoke<T, T1, T2>(T1 arg1, T2 arg2) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2>)actions[i];
try
{
action?.Invoke(arg1, arg2);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2>(Action<T1, T2> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2>(Action<T1, T2> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 三参数的事件处理
public static void Invoke<T, T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2, T3>)actions[i];
try
{
action?.Invoke(arg1, arg2, arg3);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2, T3>(Action<T1, T2, T3> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2, T3>(Action<T1, T2, T3> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 四参数的事件处理
public static void Invoke<T, T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2, T3, T4>)actions[i];
try
{
action?.Invoke(arg1, arg2, arg3, arg4);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2, T3, T4>(Action<T1, T2, T3, T4> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2, T3, T4>(Action<T1, T2, T3, T4> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 五参数的事件处理
public static void Invoke<T, T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2, T3, T4, T5>)actions[i];
try
{
action?.Invoke(arg1, arg2, arg3, arg4, arg5);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
}
}
Ib_EventAsync——异步事件中心:基于Unitask异步,实用性与可靠性暂未验证,包含同步事件的延迟一帧调用拓展,延迟调用基于Ib_Async的延迟方法。
对于耗时的任务可以通过异步的方式避免造成主线程卡顿。
*已经执行的且在等待中的异步任务,在取消订阅时需要通过令牌手动取消。(将取消令牌传递给异步方法中的延迟方法,在取消订阅时手动取消,注意延迟方法需要被try{}catch{}包裹,否则会取消后抛出的异常会阻塞异步事件的执行。)
使用示例:
using Ib_Core;
using UnityEngine;
//创建一个异步事件,有一个string参数
public class OnGameLogAsync : Ib_EventAsync<OnGameLogAsync,string> { };
public class Sample_Ib_Event_Launcher : MonoBehaviour
{
async void Start()
{
Ib_Log.Info($"[{System.DateTime.Now}]>> 准备调用异步事件");
Ib_Log.Info($"[{System.DateTime.Now}]>> 调用异步事件开始");
//调用并等待所有订阅的异步方法完成
await OnGameLogAsync.InvokeAsync("你好哦,我要等你完成");
Ib_Log.Info($"[{System.DateTime.Now}]>> 调用异步事件完毕");
}
}
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using Ib_Core;
using UnityEngine;
public class Sameple_Ib_Event_Listner : MonoBehaviour
{
//取消异步事件任务的令牌
private CancellationTokenSource eventAsyncCts;
private void Awake()
{
OnGameLogAsync.RegisterAsync(Log_SampleAsync);
OnGameLogAsync.RegisterAsync(Log_SampleAsync5);
eventAsyncCts = new CancellationTokenSource();
}
private void OnDestroy()
{
//手动管理异步事件任务的生命周期
if (eventAsyncCts != null)
{
eventAsyncCts.Cancel();
eventAsyncCts.Dispose();
eventAsyncCts = null;
}
OnGameLogAsync.DeregisterAsync(Log_SampleAsync);
OnGameLogAsync.DeregisterAsync(Log_SampleAsync5);
}
private async UniTask Log_SampleAsync(string message)
{
try
{
await UniTask.Delay(TimeSpan.FromSeconds(2),cancellationToken:eventAsyncCts.Token);
Ib_Log.Info($"[{System.DateTime.Now}]>> 监听到事件,2秒后执行:{message}");
}
catch (OperationCanceledException)
{
Ib_Log.Info("任务已取消");
}
}
private async UniTask Log_SampleAsync5(string message)
{
try
{
await UniTask.Delay(TimeSpan.FromSeconds(10),cancellationToken:eventAsyncCts.Token);
Ib_Log.Info($"[{System.DateTime.Now}]>> 监听到事件,10秒后执行:{message}");
}
catch (OperationCanceledException)
{
Ib_Log.Info("任务已取消");
}
}
}


源码:
// =================================================================================
// Ib_EventAsync - 异步事件中心
// ---------------------------------------------------------------------------------
// 这是一个独立的、类型安全的异步事件系统,使用 UniTask 实现高性能的异步操作。
//
// 使用方法:
// 1. 声明一个事件类,继承 Ib_EventAsync:
// public class OnSaveGameAsync : Ib_EventAsync<OnSaveGameAsync> { };
// public class OnDataLoadedAsync : Ib_EventAsync<OnDataLoadedAsync, string, int> { };
//
// 2. 在需要监听事件的地方注册异步方法:
// private async UniTask SaveGameHandler() { ... }
// OnSaveGameAsync.RegisterAsync(SaveGameHandler);
//
// 3. 在需要触发事件的地方调用:
// await OnSaveGameAsync.InvokeAsync();
//
// 4. 在不再需要监听时注销 (例如在 OnDestroy 中):
// OnSaveGameAsync.DeregisterAsync(SaveGameHandler);
// =================================================================================
using System.Threading;
namespace Ib_Core
{
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
// 标记接口,用于泛型约束
internal interface IIb_EventAsync
{
}
#region 零参数事件基类延迟拓展
public abstract partial class Ib_Event<T> : IIb_Event where T : Ib_Event<T>
{
private static readonly Action CachedInvokeAction = Ib_EventHandler.Invoke<T>;
public static void InvokeNextFrame(CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, cts);
}
#endregion
#region 单参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1> : IIb_Event where T : Ib_Event<T, T1>
{
private static readonly Action<T1> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1>;
public static void InvokeNextFrame(T1 arg1, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, cts);
}
#endregion
#region 双参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2> : IIb_Event where T : Ib_Event<T, T1, T2>
{
private static readonly Action<T1, T2> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, cts);
}
#endregion
#region 三参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2, T3> : IIb_Event where T : Ib_Event<T, T1, T2, T3>
{
private static readonly Action<T1, T2, T3> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2, T3>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, T3 arg3, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, arg3, cts);
}
#endregion
#region 四参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2, T3, T4> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4>
{
private static readonly Action<T1, T2, T3, T4> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2, T3, T4>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, T3 arg3, T4 arg4, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, arg3, arg4, cts);
}
#endregion
#region 五参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2, T3, T4, T5> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4, T5>
{
private static readonly Action<T1, T2, T3, T4, T5> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2, T3, T4, T5>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, arg3, arg4, arg5, cts);
}
#endregion
#region 零参数异步事件
public abstract class Ib_EventAsync<T> : IIb_EventAsync where T : Ib_EventAsync<T>
{
public static UniTask InvokeAsync() => Ib_EventHandler.InvokeAsync<T>();
public static void RegisterAsync(Func<UniTask> action) => Ib_EventHandler.RegisterAsync<T>(action);
public static void DeregisterAsync(Func<UniTask> action) => Ib_EventHandler.DeregisterAsync<T>(action);
}
#endregion
#region 单参数异步事件
public abstract class Ib_EventAsync<T, T1> : IIb_EventAsync where T : Ib_EventAsync<T, T1>
{
public static UniTask InvokeAsync(T1 arg1) => Ib_EventHandler.InvokeAsync<T, T1>(arg1);
public static void RegisterAsync(Func<T1, UniTask> action) => Ib_EventHandler.RegisterAsync<T, T1>(action);
public static void DeregisterAsync(Func<T1, UniTask> action) => Ib_EventHandler.DeregisterAsync<T, T1>(action);
}
#endregion
#region 双参数异步事件
public abstract class Ib_EventAsync<T, T1, T2> : IIb_EventAsync where T : Ib_EventAsync<T, T1, T2>
{
public static UniTask InvokeAsync(T1 arg1, T2 arg2) => Ib_EventHandler.InvokeAsync<T, T1, T2>(arg1, arg2);
public static void RegisterAsync(Func<T1, T2, UniTask> action) => Ib_EventHandler.RegisterAsync<T, T1, T2>(action);
public static void DeregisterAsync(Func<T1, T2, UniTask> action) => Ib_EventHandler.DeregisterAsync<T, T1, T2>(action);
}
#endregion
#region 三参数异步事件
public abstract class Ib_EventAsync<T, T1, T2, T3> : IIb_EventAsync where T : Ib_EventAsync<T, T1, T2, T3>
{
public static UniTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3) => Ib_EventHandler.InvokeAsync<T, T1, T2, T3>(arg1, arg2, arg3);
public static void RegisterAsync(Func<T1, T2, T3, UniTask> action) => Ib_EventHandler.RegisterAsync<T, T1, T2, T3>(action);
public static void DeregisterAsync(Func<T1, T2, T3, UniTask> action) => Ib_EventHandler.DeregisterAsync<T, T1, T2, T3>(action);
}
#endregion
#region 四参数异步事件
public abstract class Ib_EventAsync<T, T1, T2, T3, T4> : IIb_EventAsync where T : Ib_EventAsync<T, T1, T2, T3, T4>
{
public static UniTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4) => Ib_EventHandler.InvokeAsync<T, T1, T2, T3, T4>(arg1, arg2, arg3, arg4);
public static void RegisterAsync(Func<T1, T2, T3, T4, UniTask> action) => Ib_EventHandler.RegisterAsync<T, T1, T2, T3, T4>(action);
public static void DeregisterAsync(Func<T1, T2, T3, T4, UniTask> action) => Ib_EventHandler.DeregisterAsync<T, T1, T2, T3, T4>(action);
}
#endregion
#region 五参数异步事件
public abstract class Ib_EventAsync<T, T1, T2, T3, T4, T5> : IIb_EventAsync
where T : Ib_EventAsync<T, T1, T2, T3, T4, T5>
{
public static UniTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => Ib_EventHandler.InvokeAsync<T, T1, T2, T3, T4, T5>(arg1, arg2, arg3, arg4, arg5);
public static void RegisterAsync(Func<T1, T2, T3, T4, T5, UniTask> action) => Ib_EventHandler.RegisterAsync<T, T1, T2, T3, T4, T5>(action);
public static void DeregisterAsync(Func<T1, T2, T3, T4, T5, UniTask> action) => Ib_EventHandler.DeregisterAsync<T, T1, T2, T3, T4, T5>(action);
}
#endregion
internal class Ib_EventContainerAsync
{
private readonly List<Delegate> _actionList = new List<Delegate>();
private Delegate[] _cachedActions = Array.Empty<Delegate>();
private bool _isDirty = false;
public bool IsEmpty => _actionList.Count == 0;
public Delegate[] GetActions()
{
if (_isDirty)
{
_cachedActions = _actionList.ToArray();
_isDirty = false;
}
return _cachedActions;
}
public void Add(Delegate callback)
{
if (callback == null) return;
_actionList.Add(callback);
_isDirty = true;
}
public void Remove(Delegate callback)
{
if (callback == null) return;
if (_actionList.Remove(callback))
{
_isDirty = true;
}
}
}
internal static partial class Ib_EventHandler
{
private static readonly Dictionary<Type, Ib_EventContainerAsync> AsyncEventsDict = new();
private static readonly object _asyncLock = new object();
// 辅助方法:获取快照
private static Delegate[] GetAsyncSnapshot(Type type)
{
lock (_asyncLock)
{
if (AsyncEventsDict.TryGetValue(type, out var container))
{
return container.GetActions();
}
}
return null;
}
// 通用注册/注销逻辑
private static void RegisterAsyncDelegate(Type eventType, Delegate action)
{
lock (_asyncLock)
{
if (!AsyncEventsDict.TryGetValue(eventType, out var container))
{
container = new Ib_EventContainerAsync();
AsyncEventsDict[eventType] = container;
}
container.Add(action);
}
}
private static void DeregisterAsyncDelegate(Type eventType, Delegate action)
{
lock (_asyncLock)
{
if (AsyncEventsDict.TryGetValue(eventType, out var container))
{
container.Remove(action);
// 如果空了,清理字典 key,防止内存泄漏
if (container.IsEmpty)
{
AsyncEventsDict.Remove(eventType);
}
}
}
}
#region 零参数异步处理
public static void RegisterAsync<T>(Func<UniTask> action) where T : IIb_EventAsync => RegisterAsyncDelegate(typeof(T), action);
public static void DeregisterAsync<T>(Func<UniTask> action) where T : IIb_EventAsync => DeregisterAsyncDelegate(typeof(T), action);
public static async UniTask InvokeAsync<T>() where T : IIb_EventAsync
{
var actions = GetAsyncSnapshot(typeof(T));
if (actions == null || actions.Length == 0) return;
if (actions.Length == 1)
{
try
{
await ((Func<UniTask>)actions[0]).Invoke();
}
catch (Exception ex)
{
Ib_Log.Error($"Error in async event {typeof(T).Name}: {ex}");
}
return;
}
var tasks = new UniTask[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
try
{
tasks[i] = ((Func<UniTask>)actions[i]).Invoke();
}
catch (Exception ex)
{
Ib_Log.Error($"Error starting async event {typeof(T).Name}: {ex}");
tasks[i] = UniTask.CompletedTask; // 发生同步错误时填补空位
}
}
// 等待所有任务
await UniTask.WhenAll(tasks);
}
#endregion
#region 单参数异步处理
public static void RegisterAsync<T, T1>(Func<T1, UniTask> action) where T : IIb_EventAsync => RegisterAsyncDelegate(typeof(T), action);
public static void DeregisterAsync<T, T1>(Func<T1, UniTask> action) where T : IIb_EventAsync => DeregisterAsyncDelegate(typeof(T), action);
public static async UniTask InvokeAsync<T, T1>(T1 arg1) where T : IIb_EventAsync
{
var actions = GetAsyncSnapshot(typeof(T));
if (actions == null || actions.Length == 0) return;
if (actions.Length == 1)
{
try
{
await ((Func<T1, UniTask>)actions[0]).Invoke(arg1);
}
catch (Exception ex)
{
Ib_Log.Error($"Error in async event {typeof(T).Name}: {ex}");
}
return;
}
var tasks = new UniTask[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
try
{
tasks[i] = ((Func<T1, UniTask>)actions[i]).Invoke(arg1);
}
catch (Exception ex)
{
Ib_Log.Error($"Error starting async event {typeof(T).Name}: {ex}");
tasks[i] = UniTask.CompletedTask;
}
}
await UniTask.WhenAll(tasks);
}
#endregion
#region 双参数异步处理
public static void RegisterAsync<T, T1, T2>(Func<T1, T2, UniTask> action) where T : IIb_EventAsync => RegisterAsyncDelegate(typeof(T), action);
public static void DeregisterAsync<T, T1, T2>(Func<T1, T2, UniTask> action) where T : IIb_EventAsync => DeregisterAsyncDelegate(typeof(T), action);
public static async UniTask InvokeAsync<T, T1, T2>(T1 arg1, T2 arg2) where T : IIb_EventAsync
{
var actions = GetAsyncSnapshot(typeof(T));
if (actions == null || actions.Length == 0) return;
if (actions.Length == 1)
{
try
{
await ((Func<T1, T2, UniTask>)actions[0]).Invoke(arg1, arg2);
}
catch (Exception ex)
{
Ib_Log.Error($"Error in async event {typeof(T).Name}: {ex}");
}
return;
}
var tasks = new UniTask[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
try
{
tasks[i] = ((Func<T1, T2, UniTask>)actions[i]).Invoke(arg1, arg2);
}
catch (Exception ex)
{
Ib_Log.Error($"Error starting async event {typeof(T).Name}: {ex}");
tasks[i] = UniTask.CompletedTask;
}
}
await UniTask.WhenAll(tasks);
}
#endregion
#region 三参数异步处理
public static void RegisterAsync<T, T1, T2, T3>(Func<T1, T2, T3, UniTask> action) where T : IIb_EventAsync => RegisterAsyncDelegate(typeof(T), action);
public static void DeregisterAsync<T, T1, T2, T3>(Func<T1, T2, T3, UniTask> action) where T : IIb_EventAsync => DeregisterAsyncDelegate(typeof(T), action);
public static async UniTask InvokeAsync<T, T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3) where T : IIb_EventAsync
{
var actions = GetAsyncSnapshot(typeof(T));
if (actions == null || actions.Length == 0) return;
if (actions.Length == 1)
{
try
{
await ((Func<T1, T2, T3, UniTask>)actions[0]).Invoke(arg1, arg2, arg3);
}
catch (Exception ex)
{
Ib_Log.Error($"Error in async event {typeof(T).Name}: {ex}");
}
return;
}
var tasks = new UniTask[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
try
{
tasks[i] = ((Func<T1, T2, T3, UniTask>)actions[i]).Invoke(arg1, arg2, arg3);
}
catch (Exception ex)
{
Ib_Log.Error($"Error starting async event {typeof(T).Name}: {ex}");
tasks[i] = UniTask.CompletedTask;
}
}
await UniTask.WhenAll(tasks);
}
#endregion
#region 四参数异步处理
public static void RegisterAsync<T, T1, T2, T3, T4>(Func<T1, T2, T3, T4, UniTask> action) where T : IIb_EventAsync => RegisterAsyncDelegate(typeof(T), action);
public static void DeregisterAsync<T, T1, T2, T3, T4>(Func<T1, T2, T3, T4, UniTask> action) where T : IIb_EventAsync => DeregisterAsyncDelegate(typeof(T), action);
public static async UniTask InvokeAsync<T, T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4) where T : IIb_EventAsync
{
var actions = GetAsyncSnapshot(typeof(T));
if (actions == null || actions.Length == 0) return;
if (actions.Length == 1)
{
try
{
await ((Func<T1, T2, T3, T4, UniTask>)actions[0]).Invoke(arg1, arg2, arg3, arg4);
}
catch (Exception ex)
{
Ib_Log.Error($"Error in async event {typeof(T).Name}: {ex}");
}
return;
}
var tasks = new UniTask[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
try
{
tasks[i] = ((Func<T1, T2, T3, T4, UniTask>)actions[i]).Invoke(arg1, arg2, arg3, arg4);
}
catch (Exception ex)
{
Ib_Log.Error($"Error starting async event {typeof(T).Name}: {ex}");
tasks[i] = UniTask.CompletedTask;
}
}
await UniTask.WhenAll(tasks);
}
#endregion
#region 五参数异步处理
public static void RegisterAsync<T, T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, UniTask> action) where T : IIb_EventAsync => RegisterAsyncDelegate(typeof(T), action);
public static void DeregisterAsync<T, T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, UniTask> action) where T : IIb_EventAsync => DeregisterAsyncDelegate(typeof(T), action);
public static async UniTask InvokeAsync<T, T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) where T : IIb_EventAsync
{
var actions = GetAsyncSnapshot(typeof(T));
if (actions == null || actions.Length == 0) return;
if (actions.Length == 1)
{
try
{
await ((Func<T1, T2, T3, T4, T5, UniTask>)actions[0]).Invoke(arg1, arg2, arg3, arg4, arg5);
}
catch (Exception ex)
{
Ib_Log.Error($"Error in async event {typeof(T).Name}: {ex}");
}
return;
}
var tasks = new UniTask[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
try
{
tasks[i] = ((Func<T1, T2, T3, T4, T5, UniTask>)actions[i]).Invoke(arg1, arg2, arg3, arg4, arg5);
}
catch (Exception ex)
{
Ib_Log.Error($"Error starting async event {typeof(T).Name}: {ex}");
tasks[i] = UniTask.CompletedTask;
}
}
await UniTask.WhenAll(tasks);
}
#endregion
}
}
评论(0)
暂无评论