mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 19:03:29 +08:00
- 定义了IPageBehavior接口,提供UI页面的生命周期方法如OnEnter、OnExit、OnPause、OnResume等 - 创建了IUiFactory接口用于创建UI页面实例,以及IUiPage接口定义页面基本操作 - 添加了IUiPageEnterParam接口用于定义页面跳转参数数据结构 - 实现了IUiRouter接口提供页面栈管理功能,支持Push、Pop、Replace、Clear等操作 - 创建了UI切换处理器相关接口和实现,包括IUiTransitionHandler和UiTransitionPipeline - 添加了UI切换事件系统,支持BeforeChange和AfterChange两个执行阶段 - 实现了日志记录处理器LoggingTransitionHandler用于记录UI切换信息 - 定义了多种UI切换策略枚举如UiTransitionPolicy、UiTransitionType等 - 提供了UI注册表接口用于管理UI实例的注册和获取功能
168 lines
5.3 KiB
C#
168 lines
5.3 KiB
C#
using GFramework.Core.Abstractions.logging;
|
||
using GFramework.Core.logging;
|
||
using GFramework.Game.Abstractions.enums;
|
||
using GFramework.Game.Abstractions.ui;
|
||
|
||
namespace GFramework.Game.ui;
|
||
|
||
/// <summary>
|
||
/// UI切换处理器管道,负责管理和执行UI切换扩展点
|
||
/// </summary>
|
||
public class UiTransitionPipeline
|
||
{
|
||
private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger("UiTransitionPipeline");
|
||
private readonly List<IUiTransitionHandler> _handlers = new();
|
||
private readonly Dictionary<IUiTransitionHandler, UiTransitionHandlerOptions> _options = new();
|
||
|
||
/// <summary>
|
||
/// 注册UI切换处理器
|
||
/// </summary>
|
||
/// <param name="handler">处理器实例</param>
|
||
/// <param name="options">执行选项</param>
|
||
public void RegisterHandler(IUiTransitionHandler handler, UiTransitionHandlerOptions? options = null)
|
||
{
|
||
ArgumentNullException.ThrowIfNull(handler);
|
||
|
||
if (_handlers.Contains(handler))
|
||
{
|
||
Log.Debug("Handler already registered: {0}", handler.GetType().Name);
|
||
return;
|
||
}
|
||
|
||
_handlers.Add(handler);
|
||
_options[handler] = options ?? new UiTransitionHandlerOptions();
|
||
Log.Debug(
|
||
"Handler registered: {0}, Priority={1}, Phases={2}, TimeoutMs={3}",
|
||
handler.GetType().Name,
|
||
handler.Priority,
|
||
handler.Phases,
|
||
_options[handler].TimeoutMs
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注销UI切换处理器
|
||
/// </summary>
|
||
/// <param name="handler">处理器实例</param>
|
||
public void UnregisterHandler(IUiTransitionHandler handler)
|
||
{
|
||
ArgumentNullException.ThrowIfNull(handler);
|
||
|
||
if (!_handlers.Remove(handler)) return;
|
||
_options.Remove(handler);
|
||
Log.Debug("Handler unregistered: {0}", handler.GetType().Name);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行指定阶段的所有Handler
|
||
/// </summary>
|
||
/// <param name="event">UI切换事件</param>
|
||
/// <param name="phases">执行阶段</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>异步任务</returns>
|
||
public async Task ExecuteAsync(
|
||
UiTransitionEvent @event,
|
||
UITransitionPhases phases,
|
||
CancellationToken cancellationToken = default
|
||
)
|
||
{
|
||
@event.Set("Phases", phases.ToString());
|
||
|
||
Log.Debug(
|
||
"Execute pipeline: Phases={0}, From={1}, To={2}, Type={3}, HandlerCount={4}",
|
||
phases,
|
||
@event.FromUiKey,
|
||
@event.ToUiKey,
|
||
@event.TransitionType,
|
||
_handlers.Count
|
||
);
|
||
|
||
var sortedHandlers = FilterAndSortHandlers(@event, phases);
|
||
|
||
if (sortedHandlers.Count == 0)
|
||
{
|
||
Log.Debug("No handlers to execute for phases: {0}", phases);
|
||
return;
|
||
}
|
||
|
||
Log.Debug(
|
||
"Executing {0} handlers for phases {1}",
|
||
sortedHandlers.Count,
|
||
phases
|
||
);
|
||
|
||
foreach (var handler in sortedHandlers)
|
||
{
|
||
var options = _options[handler];
|
||
await ExecuteSingleHandlerAsync(handler, options, @event, cancellationToken);
|
||
}
|
||
|
||
Log.Debug("Pipeline execution completed for phases: {0}", phases);
|
||
}
|
||
|
||
private List<IUiTransitionHandler> FilterAndSortHandlers(
|
||
UiTransitionEvent @event,
|
||
UITransitionPhases phases)
|
||
{
|
||
return _handlers
|
||
.Where(h => h.Phases.HasFlag(phases) && h.ShouldHandle(@event, phases))
|
||
.OrderBy(h => h.Priority)
|
||
.ToList();
|
||
}
|
||
|
||
private static async Task ExecuteSingleHandlerAsync(
|
||
IUiTransitionHandler handler,
|
||
UiTransitionHandlerOptions options,
|
||
UiTransitionEvent @event,
|
||
CancellationToken cancellationToken)
|
||
{
|
||
Log.Debug(
|
||
"Executing handler: {0}, Priority={1}",
|
||
handler.GetType().Name,
|
||
handler.Priority
|
||
);
|
||
|
||
try
|
||
{
|
||
using var timeoutCts = options.TimeoutMs > 0
|
||
? new CancellationTokenSource(options.TimeoutMs)
|
||
: null;
|
||
|
||
using var linkedCts = timeoutCts != null && cancellationToken.CanBeCanceled
|
||
? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token)
|
||
: null;
|
||
|
||
await handler.HandleAsync(
|
||
@event,
|
||
linkedCts?.Token ?? cancellationToken
|
||
).ConfigureAwait(false);
|
||
|
||
Log.Debug("Handler completed: {0}", handler.GetType().Name);
|
||
}
|
||
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
|
||
{
|
||
Log.Error(
|
||
"Handler timeout: {0}, TimeoutMs={1}",
|
||
handler.GetType().Name,
|
||
options.TimeoutMs
|
||
);
|
||
|
||
if (options.ContinueOnError) return;
|
||
Log.Error("Stopping pipeline due to timeout and ContinueOnError=false");
|
||
throw;
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
Log.Debug("Handler cancelled: {0}", handler.GetType().Name);
|
||
throw;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error("Handler failed: {0}, Error: {1}", handler.GetType().Name, ex.Message);
|
||
|
||
if (options.ContinueOnError) return;
|
||
Log.Error("Stopping pipeline due to error and ContinueOnError=false");
|
||
throw;
|
||
}
|
||
}
|
||
} |