feat(event-kit): 添加 SingleCastEventSystem 单播事件系统
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// 单播事件系统
|
||||
/// 特点:通过枚举索引事件,多处可触发,但仅有一个方法能被注册(后注册覆盖先注册)
|
||||
/// 用途:用于解耦项目中的单例依赖
|
||||
/// </summary>
|
||||
public class SingleCastEventSystem
|
||||
{
|
||||
public static readonly SingleCastEventSystem Global = new();
|
||||
|
||||
// 内部接口:用于统一存储不同类型的事件
|
||||
private interface IEventEntry
|
||||
{
|
||||
}
|
||||
|
||||
// 类型化的条目存储
|
||||
private class Entry<T> : IEventEntry where T : Delegate
|
||||
{
|
||||
public T Handler;
|
||||
}
|
||||
|
||||
// 按枚举类型分组的存储
|
||||
// Key: 枚举类型, Value: 该枚举所有值的条目数组
|
||||
private readonly Dictionary<Type, IEventEntry[]> _entries = new(50);
|
||||
|
||||
#region 无参数
|
||||
|
||||
public void Register<T>(T key, Action handler) where T : IConvertible
|
||||
{
|
||||
var entry = GetEntry<T, Action>(key);
|
||||
|
||||
#if DEBUG
|
||||
if (entry.Handler != null)
|
||||
{
|
||||
Debug.LogWarning($"[SingleCastEvent] {typeof(T).Name}.{key} 已被注册,正在覆盖");
|
||||
}
|
||||
#endif
|
||||
|
||||
entry.Handler = handler;
|
||||
}
|
||||
|
||||
public void Trigger<T>(T key) where T : IConvertible
|
||||
{
|
||||
var entry = GetEntryOrNull<T, Action>(key);
|
||||
entry?.Handler?.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 1个参数
|
||||
|
||||
public void Register<T, T1>(T key, Action<T1> handler) where T : IConvertible
|
||||
{
|
||||
var entry = GetEntry<T, Action<T1>>(key);
|
||||
|
||||
#if DEBUG
|
||||
if (entry.Handler != null)
|
||||
{
|
||||
Debug.LogWarning($"[SingleCastEvent] {typeof(T).Name}.{key} 已被注册,正在覆盖");
|
||||
}
|
||||
#endif
|
||||
|
||||
entry.Handler = handler;
|
||||
}
|
||||
|
||||
public void Trigger<T, T1>(T key, T1 arg1) where T : IConvertible
|
||||
{
|
||||
var entry = GetEntryOrNull<T, Action<T1>>(key);
|
||||
entry?.Handler?.Invoke(arg1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 2个参数
|
||||
|
||||
public void Register<T, T1, T2>(T key, Action<T1, T2> handler) where T : IConvertible
|
||||
{
|
||||
var entry = GetEntry<T, Action<T1, T2>>(key);
|
||||
|
||||
#if DEBUG
|
||||
if (entry.Handler != null)
|
||||
{
|
||||
Debug.LogWarning($"[SingleCastEvent] {typeof(T).Name}.{key} 已被注册,正在覆盖");
|
||||
}
|
||||
#endif
|
||||
|
||||
entry.Handler = handler;
|
||||
}
|
||||
|
||||
public void Trigger<T, T1, T2>(T key, T1 arg1, T2 arg2) where T : IConvertible
|
||||
{
|
||||
var entry = GetEntryOrNull<T, Action<T1, T2>>(key);
|
||||
entry?.Handler?.Invoke(arg1, arg2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 注销
|
||||
|
||||
public void Unregister<T>(T key) where T : IConvertible
|
||||
{
|
||||
var index = key.ToInt32(null);
|
||||
var enumType = typeof(T);
|
||||
|
||||
if (_entries.TryGetValue(enumType, out var arr) && index < arr.Length)
|
||||
{
|
||||
arr[index] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterAll()
|
||||
{
|
||||
_entries.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 内部辅助方法
|
||||
|
||||
private Entry<TDelegate> GetEntry<TEnum, TDelegate>(TEnum key)
|
||||
where TEnum : IConvertible
|
||||
where TDelegate : Delegate
|
||||
{
|
||||
var index = key.ToInt32(null);
|
||||
var enumType = typeof(TEnum);
|
||||
|
||||
if (!_entries.TryGetValue(enumType, out var arr))
|
||||
{
|
||||
// 首次使用该枚举类型,创建条目数组
|
||||
var valueCount = Enum.GetValues(enumType).Length;
|
||||
arr = new IEventEntry[valueCount];
|
||||
_entries[enumType] = arr;
|
||||
}
|
||||
|
||||
if (arr[index] == null)
|
||||
{
|
||||
arr[index] = new Entry<TDelegate>();
|
||||
}
|
||||
|
||||
return (Entry<TDelegate>)arr[index];
|
||||
}
|
||||
|
||||
private Entry<TDelegate> GetEntryOrNull<TEnum, TDelegate>(TEnum key)
|
||||
where TEnum : IConvertible
|
||||
where TDelegate : Delegate
|
||||
{
|
||||
var index = key.ToInt32(null);
|
||||
var enumType = typeof(TEnum);
|
||||
|
||||
if (!_entries.TryGetValue(enumType, out var arr)) return null;
|
||||
if (index >= arr.Length) return null;
|
||||
|
||||
return arr[index] as Entry<TDelegate>;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user