TH1/Unity/Assets/Scripts/Logic/Event/EventManager.cs
2025-07-30 18:03:37 +08:00

93 lines
3.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: 白哉
* @Description:
* @Date: 2025年07月01日 星期二 19:07:32
* @Modify:
*/
using System;
using System.Collections.Generic;
using RuntimeData;
using TH1Renderer;
namespace Logic.Event
{
public static class EventManager
{
// 使用一个字典来存储所有事件的订阅者。
// 键(Key)是事件的类型(Type),值(Value)是响应该事件的委托(Delegate)。
private static Dictionary<Type, Delegate> eventListeners = new Dictionary<Type, Delegate>();
/// <summary>
/// 订阅一个事件。
/// </summary>
/// <typeparam name="T">要订阅的事件类型必须是struct。</typeparam>
/// <param name="listener">事件发生时要执行的回调方法。</param>
public static void Subscribe<T>(Action<T> listener) where T : struct
{
Type eventType = typeof(T);
// 如果字典中已存在该事件类型的委托
if (eventListeners.TryGetValue(eventType, out Delegate existingDelegate))
{
// 将新的监听器添加到现有委托链中
eventListeners[eventType] = Delegate.Combine(existingDelegate, listener);
}
else // 如果是第一次订阅该事件
{
// 直接将监听器作为新的委托存入字典
eventListeners[eventType] = listener;
}
}
/// <summary>
/// 取消订阅一个事件。
/// </summary>
/// <typeparam name="T">要取消订阅的事件类型必须是struct。</typeparam>
/// <param name="listener">之前订阅时使用的回调方法。</param>
public static void Unsubscribe<T>(Action<T> listener) where T : struct
{
Type eventType = typeof(T);
// 只有在字典中存在该事件类型时才进行操作
if (eventListeners.TryGetValue(eventType, out Delegate existingDelegate))
{
// 从委托链中移除指定的监听器
Delegate resultDelegate = Delegate.Remove(existingDelegate, listener);
// 如果移除后委托链不为空,则更新字典
if (resultDelegate != null)
{
eventListeners[eventType] = resultDelegate;
}
else // 如果移除后委托链为空,则从字典中移除该事件类型
{
eventListeners.Remove(eventType);
}
}
}
/// <summary>
/// 发布一个事件。
/// 所有订阅了该事件的监听器都将被同步调用。
/// </summary>
/// <typeparam name="T">要发布的事件类型必须是struct。</typeparam>
/// <param name="eventData">要传递给监听器的事件数据。</param>
public static void Publish<T>(T eventData) where T : struct
{
Type eventType = typeof(T);
// 尝试从字典中获取该事件的委托链
if (eventListeners.TryGetValue(eventType, out Delegate existingDelegate))
{
// 将通用的 Delegate 类型安全地转换为具体的 Action<T> 类型
// 使用 ?.Invoke() 可以安全地调用,即使委托为空也不会抛出异常
var action = existingDelegate as Action<T>;
action?.Invoke(eventData);
}
// 如果没有找到任何订阅者,则什么也不做。这是一种正常情况。
}
}
}