mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 16:55:57 +08:00
- 迁移 Events、Property、State 与 Coroutine 中 7 个类型的监视器字段到 NET9_0_OR_GREATER 专用 Lock 模式 - 保持 net8.0 的 object 回退路径以兼容多目标构建 - 更新 BindableProperty 的同步注释以匹配新的多目标同步原语
336 lines
11 KiB
C#
336 lines
11 KiB
C#
using GFramework.Core.Abstractions.Events;
|
||
|
||
namespace GFramework.Core.Events;
|
||
|
||
/// <summary>
|
||
/// 支持优先级的泛型事件类
|
||
/// </summary>
|
||
/// <typeparam name="T">事件回调函数的参数类型</typeparam>
|
||
public class PriorityEvent<T> : IEvent
|
||
{
|
||
/// <summary>
|
||
/// 存储已注册的上下文事件处理器列表
|
||
/// </summary>
|
||
private readonly List<ContextEventHandler> _contextHandlers = new();
|
||
|
||
/// <summary>
|
||
/// 存储已注册的事件处理器列表
|
||
/// </summary>
|
||
private readonly List<EventHandler> _handlers = new();
|
||
|
||
/// <summary>
|
||
/// 保护处理器集合的并发访问
|
||
/// </summary>
|
||
#if NET9_0_OR_GREATER
|
||
// net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
|
||
private readonly System.Threading.Lock _syncRoot = new();
|
||
#else
|
||
// net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
|
||
private readonly object _syncRoot = new();
|
||
#endif
|
||
|
||
/// <summary>
|
||
/// 标记事件是否已被处理(用于 UntilHandled 传播模式)
|
||
/// </summary>
|
||
private bool _handled;
|
||
|
||
/// <summary>
|
||
/// 显式实现 IEvent 接口中的 Register 方法
|
||
/// </summary>
|
||
/// <param name="onEvent">无参事件处理方法</param>
|
||
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器</returns>
|
||
IUnRegister IEvent.Register(Action onEvent)
|
||
{
|
||
return Register(_ => onEvent(), 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册一个事件监听器,默认优先级为 0
|
||
/// </summary>
|
||
/// <param name="onEvent">要注册的事件处理方法</param>
|
||
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器</returns>
|
||
public IUnRegister Register(Action<T> onEvent)
|
||
{
|
||
return Register(onEvent, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册一个事件监听器,并指定优先级
|
||
/// </summary>
|
||
/// <param name="onEvent">要注册的事件处理方法</param>
|
||
/// <param name="priority">优先级,数值越大优先级越高</param>
|
||
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器</returns>
|
||
public IUnRegister Register(Action<T> onEvent, int priority)
|
||
{
|
||
var handler = new EventHandler(onEvent, priority);
|
||
lock (_syncRoot)
|
||
{
|
||
_handlers.Add(handler);
|
||
|
||
// 按优先级降序排序(高优先级在前)
|
||
_handlers.Sort((a, b) => b.Priority.CompareTo(a.Priority));
|
||
}
|
||
|
||
return new DefaultUnRegister(() => UnRegister(onEvent));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消指定的事件监听器
|
||
/// </summary>
|
||
/// <param name="onEvent">需要被注销的事件处理方法</param>
|
||
public void UnRegister(Action<T> onEvent)
|
||
{
|
||
lock (_syncRoot)
|
||
{
|
||
_handlers.RemoveAll(h => h.Handler == onEvent);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册一个上下文事件监听器,并指定优先级
|
||
/// </summary>
|
||
/// <param name="onEvent">要注册的事件处理方法,接收 EventContext 参数</param>
|
||
/// <param name="priority">优先级,数值越大优先级越高</param>
|
||
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器</returns>
|
||
public IUnRegister RegisterWithContext(Action<EventContext<T>> onEvent, int priority = 0)
|
||
{
|
||
var handler = new ContextEventHandler(onEvent, priority);
|
||
lock (_syncRoot)
|
||
{
|
||
_contextHandlers.Add(handler);
|
||
|
||
// 按优先级降序排序(高优先级在前)
|
||
_contextHandlers.Sort((a, b) => b.Priority.CompareTo(a.Priority));
|
||
}
|
||
|
||
return new DefaultUnRegister(() => UnRegisterContext(onEvent));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消指定的上下文事件监听器
|
||
/// </summary>
|
||
/// <param name="onEvent">需要被注销的事件处理方法</param>
|
||
public void UnRegisterContext(Action<EventContext<T>> onEvent)
|
||
{
|
||
lock (_syncRoot)
|
||
{
|
||
_contextHandlers.RemoveAll(h => h.Handler == onEvent);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 触发事件处理程序,并指定传播模式
|
||
/// </summary>
|
||
/// <param name="t">传递给事件处理程序的参数</param>
|
||
/// <param name="propagation">事件传播模式</param>
|
||
public void Trigger(T t, EventPropagation propagation = EventPropagation.All)
|
||
{
|
||
_handled = false;
|
||
|
||
switch (propagation)
|
||
{
|
||
case EventPropagation.All:
|
||
TriggerAll(t);
|
||
break;
|
||
|
||
case EventPropagation.UntilHandled:
|
||
TriggerUntilHandled(t);
|
||
break;
|
||
|
||
case EventPropagation.Highest:
|
||
TriggerHighest(t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 触发所有事件处理器(按优先级顺序)
|
||
/// </summary>
|
||
/// <param name="t">事件参数</param>
|
||
private void TriggerAll(T t)
|
||
{
|
||
var allHandlers = MergeAndSortHandlers(t);
|
||
var context = new EventContext<T>(t);
|
||
|
||
foreach (var item in allHandlers)
|
||
{
|
||
if (item.IsContext)
|
||
{
|
||
item.ContextHandler?.Invoke(context);
|
||
}
|
||
else
|
||
{
|
||
item.Handler?.Invoke();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 触发事件处理器直到被处理
|
||
/// </summary>
|
||
/// <param name="t">事件参数</param>
|
||
private void TriggerUntilHandled(T t)
|
||
{
|
||
var allHandlers = MergeAndSortHandlers(t);
|
||
var context = new EventContext<T>(t);
|
||
|
||
foreach (var item in allHandlers)
|
||
{
|
||
if (item.IsContext)
|
||
{
|
||
item.ContextHandler?.Invoke(context);
|
||
if (context.IsHandled) break;
|
||
}
|
||
else
|
||
{
|
||
item.Handler?.Invoke();
|
||
if (_handled) break; // 保持向后兼容
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 仅触发最高优先级的事件处理器
|
||
/// </summary>
|
||
/// <param name="t">事件参数</param>
|
||
private void TriggerHighest(T t)
|
||
{
|
||
var (normalSnapshot, contextSnapshot) = CreateSnapshots();
|
||
var highestPriority = GetHighestPriority(normalSnapshot, contextSnapshot);
|
||
|
||
if (highestPriority != int.MinValue)
|
||
{
|
||
ExecuteHighPriorityNormalHandlers(normalSnapshot, t, highestPriority);
|
||
ExecuteHighPriorityContextHandlers(contextSnapshot, t, highestPriority);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 合并并排序所有事件处理器
|
||
/// </summary>
|
||
/// <param name="t">事件参数</param>
|
||
/// <returns>合并排序后的处理器列表</returns>
|
||
private List<(int Priority, Action? Handler, Action<EventContext<T>>? ContextHandler, bool IsContext)>
|
||
MergeAndSortHandlers(T t)
|
||
{
|
||
var (normalSnapshot, contextSnapshot) = CreateSnapshots();
|
||
// 使用统一的投影方法显式固定元组的可空标注,避免 LINQ 在 Concat 时推断出不兼容的签名。
|
||
return normalSnapshot
|
||
.Select(h => CreateNormalHandlerInvocation(h, t))
|
||
.Concat(contextSnapshot.Select(CreateContextHandlerInvocation))
|
||
.OrderByDescending(h => h.Priority)
|
||
.ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取最高优先级
|
||
/// </summary>
|
||
/// <param name="normalHandlers">普通事件处理器数组</param>
|
||
/// <param name="contextHandlers">上下文事件处理器数组</param>
|
||
/// <returns>最高优先级值</returns>
|
||
private static int GetHighestPriority(EventHandler[] normalHandlers, ContextEventHandler[] contextHandlers)
|
||
{
|
||
var highestPriority = int.MinValue;
|
||
|
||
if (normalHandlers.Length > 0)
|
||
highestPriority = Math.Max(highestPriority, normalHandlers[0].Priority);
|
||
|
||
if (contextHandlers.Length > 0)
|
||
highestPriority = Math.Max(highestPriority, contextHandlers[0].Priority);
|
||
|
||
return highestPriority;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行高优先级的普通事件处理器
|
||
/// </summary>
|
||
/// <param name="handlers">处理器数组</param>
|
||
/// <param name="t">事件参数</param>
|
||
/// <param name="highestPriority">最高优先级</param>
|
||
private static void ExecuteHighPriorityNormalHandlers(EventHandler[] handlers, T t, int highestPriority)
|
||
{
|
||
foreach (var handler in handlers)
|
||
{
|
||
if (handler.Priority < highestPriority) break;
|
||
handler.Handler.Invoke(t);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行高优先级的上下文事件处理器
|
||
/// </summary>
|
||
/// <param name="handlers">处理器数组</param>
|
||
/// <param name="t">事件参数</param>
|
||
/// <param name="highestPriority">最高优先级</param>
|
||
private static void ExecuteHighPriorityContextHandlers(ContextEventHandler[] handlers, T t, int highestPriority)
|
||
{
|
||
var context = new EventContext<T>(t);
|
||
foreach (var handler in handlers)
|
||
{
|
||
if (handler.Priority < highestPriority) break;
|
||
handler.Handler.Invoke(context);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前已注册的监听器总数量(包括普通监听器和上下文监听器)
|
||
/// </summary>
|
||
/// <returns>监听器总数量</returns>
|
||
public int GetListenerCount()
|
||
{
|
||
lock (_syncRoot)
|
||
{
|
||
return _handlers.Count + _contextHandlers.Count;
|
||
}
|
||
}
|
||
|
||
private (EventHandler[] NormalHandlers, ContextEventHandler[] ContextHandlers) CreateSnapshots()
|
||
{
|
||
lock (_syncRoot)
|
||
{
|
||
return (_handlers.ToArray(), _contextHandlers.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将普通事件处理器转换为统一的调用描述。
|
||
/// </summary>
|
||
/// <param name="handler">要包装的普通处理器。</param>
|
||
/// <param name="t">当前触发的事件数据。</param>
|
||
/// <returns>可与上下文处理器合并排序的统一调用描述。</returns>
|
||
private static (int Priority, Action? Handler, Action<EventContext<T>>? ContextHandler, bool IsContext)
|
||
CreateNormalHandlerInvocation(EventHandler handler, T t)
|
||
{
|
||
return (handler.Priority, () => handler.Handler.Invoke(t), null, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将上下文事件处理器转换为统一的调用描述。
|
||
/// </summary>
|
||
/// <param name="handler">要包装的上下文处理器。</param>
|
||
/// <returns>可与普通处理器合并排序的统一调用描述。</returns>
|
||
private static (int Priority, Action? Handler, Action<EventContext<T>>? ContextHandler, bool IsContext)
|
||
CreateContextHandlerInvocation(ContextEventHandler handler)
|
||
{
|
||
return (handler.Priority, null, handler.Handler, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 事件处理器包装类,包含处理器和优先级
|
||
/// </summary>
|
||
private sealed class EventHandler(Action<T> handler, int priority)
|
||
{
|
||
public Action<T> Handler { get; } = handler;
|
||
public int Priority { get; } = priority;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 上下文事件处理器包装类,包含处理器和优先级
|
||
/// </summary>
|
||
private sealed class ContextEventHandler(Action<EventContext<T>> handler, int priority)
|
||
{
|
||
public Action<EventContext<T>> Handler { get; } = handler;
|
||
public int Priority { get; } = priority;
|
||
}
|
||
}
|