164 lines
4.4 KiB
C#
164 lines
4.4 KiB
C#
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
|
|
}
|
|
}
|