using System;
using System.Collections.Generic;
using UnityEngine;
namespace AibisDream.Framework
{
///
/// 单播事件系统
/// 特点:通过枚举索引事件,多处可触发,但仅有一个方法能被注册(后注册覆盖先注册)
/// 用途:用于解耦项目中的单例依赖
///
public class SingleCastEventSystem
{
public static readonly SingleCastEventSystem Global = new();
// 内部接口:用于统一存储不同类型的事件
private interface IEventEntry
{
}
// 类型化的条目存储
private class Entry : IEventEntry where T : Delegate
{
public T Handler;
}
// 按枚举类型分组的存储
// Key: 枚举类型, Value: 该枚举所有值的条目数组
private readonly Dictionary _entries = new(50);
#region 无参数
public void Register(T key, Action handler) where T : IConvertible
{
var entry = GetEntry(key);
#if DEBUG
if (entry.Handler != null)
{
Debug.LogWarning($"[SingleCastEvent] {typeof(T).Name}.{key} 已被注册,正在覆盖");
}
#endif
entry.Handler = handler;
}
public void Trigger(T key) where T : IConvertible
{
var entry = GetEntryOrNull(key);
entry?.Handler?.Invoke();
}
#endregion
#region 1个参数
public void Register(T key, Action handler) where T : IConvertible
{
var entry = GetEntry>(key);
#if DEBUG
if (entry.Handler != null)
{
Debug.LogWarning($"[SingleCastEvent] {typeof(T).Name}.{key} 已被注册,正在覆盖");
}
#endif
entry.Handler = handler;
}
public void Trigger(T key, T1 arg1) where T : IConvertible
{
var entry = GetEntryOrNull>(key);
entry?.Handler?.Invoke(arg1);
}
#endregion
#region 2个参数
public void Register(T key, Action handler) where T : IConvertible
{
var entry = GetEntry>(key);
#if DEBUG
if (entry.Handler != null)
{
Debug.LogWarning($"[SingleCastEvent] {typeof(T).Name}.{key} 已被注册,正在覆盖");
}
#endif
entry.Handler = handler;
}
public void Trigger(T key, T1 arg1, T2 arg2) where T : IConvertible
{
var entry = GetEntryOrNull>(key);
entry?.Handler?.Invoke(arg1, arg2);
}
#endregion
#region 注销
public void Unregister(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 GetEntry(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();
}
return (Entry)arr[index];
}
private Entry GetEntryOrNull(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;
}
#endregion
}
}