using System;
using System.Threading;
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Enums;
using GFramework.Core.Architectures;
using GFramework.Core.Utility;
using GFramework.Game.Abstractions.Config;
namespace GFramework.Game.Config;
///
/// 提供基于 的官方配置模块接入入口。
/// 该模块负责把 挂接到架构生命周期中,统一完成注册表暴露、
/// 首次加载以及架构销毁时的资源回收。
///
///
/// 使用该模块时,推荐在 Architecture.OnInitialize() 的较早位置调用 ,
/// 以便其他 utility、model 和 system 在各自初始化阶段都能读取到已经完成首次加载的配置表。
/// 如果消费项目不基于 ,则继续直接使用 更合适。
///
public sealed class GameConfigModule : IArchitectureModule
{
private readonly GameConfigBootstrap _bootstrap;
private readonly ModuleBootstrapLifetimeUtility _lifetimeUtility;
private int _installState;
///
/// 使用指定的启动选项创建配置模块。
///
/// 配置启动帮助器选项。
/// 当 为空时抛出。
///
/// 当 不满足 的构造约束时抛出。
///
public GameConfigModule(GameConfigBootstrapOptions options)
{
ArgumentNullException.ThrowIfNull(options);
_bootstrap = new GameConfigBootstrap(options);
_lifetimeUtility = new ModuleBootstrapLifetimeUtility(_bootstrap);
}
///
/// 获取当前模块复用的配置注册表。
/// 该实例会在模块安装时注册为架构 utility,供其他组件通过上下文直接读取。
///
public IConfigRegistry Registry => _bootstrap.Registry;
///
/// 获取一个值,指示模块绑定的配置启动器是否已经完成首次加载。
///
public bool IsInitialized => _bootstrap.IsInitialized;
///
/// 获取一个值,指示模块绑定的开发期热重载是否已启用。
///
public bool IsHotReloadEnabled => _bootstrap.IsHotReloadEnabled;
///
/// 获取当前生效的 YAML 配置加载器。
/// 只有在模块完成首次加载后该属性才可访问。
///
/// 当模块所属架构已销毁时抛出。
/// 当首次加载尚未成功完成时抛出。
public YamlConfigLoader Loader => _bootstrap.Loader;
///
/// 将配置模块安装到指定架构中。
/// 安装后会立即暴露 ,并注册一个生命周期钩子,
/// 以便在 utility 初始化之前完成一次确定性的配置加载。
///
/// 目标架构实例。
/// 当 为空时抛出。
/// 当同一个模块实例被重复安装时抛出。
public void Install(IArchitecture architecture)
{
ArgumentNullException.ThrowIfNull(architecture);
if (Interlocked.Exchange(ref _installState, 1) != 0)
{
throw new InvalidOperationException(
"The same GameConfigModule instance cannot be installed more than once.");
}
architecture.RegisterUtility(Registry);
architecture.RegisterUtility(_lifetimeUtility);
architecture.RegisterLifecycleHook(new BootstrapInitializationHook(_bootstrap));
}
///
/// 在首次加载成功后显式启用开发期热重载。
/// 该入口与 的语义保持一致,
/// 供已经保留模块实例引用的架构启动层按环境决定是否追加监听。
///
/// 热重载选项;为空时使用默认行为。
public void StartHotReload(YamlConfigHotReloadOptions? options = null)
{
_bootstrap.StartHotReload(options);
}
///
/// 停止开发期热重载并释放监听资源。
/// 该方法是幂等的,允许架构外部的开发期开关无条件调用。
///
public void StopHotReload()
{
_bootstrap.StopHotReload();
}
///
/// 在 utility 初始化之前完成首次配置加载的生命周期钩子。
/// 这样后续 utility、model 和 system 在各自初始化阶段就能直接依赖已加载的注册表。
///
private sealed class BootstrapInitializationHook(GameConfigBootstrap bootstrap) : IArchitectureLifecycleHook
{
///
/// 在目标阶段触发配置加载。
///
/// 当前架构阶段。
/// 相关架构实例;当前实现不直接使用,但保留用于接口契约一致性。
public void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
{
if (phase != ArchitecturePhase.BeforeUtilityInit)
{
return;
}
// 架构生命周期钩子当前是同步接口,因此这里显式桥接到统一的 bootstrap 异步实现,
// 让 Architecture 模式和独立运行时模式保持同一套加载、诊断和热重载启动语义。
bootstrap.InitializeAsync().GetAwaiter().GetResult();
}
}
///
/// 跟随架构 utility 生命周期释放底层 bootstrap 资源的薄封装。
/// 该 utility 本身不承担加载职责,只负责在架构销毁时停止热重载并释放监听句柄。
///
private sealed class ModuleBootstrapLifetimeUtility(GameConfigBootstrap bootstrap) : AbstractContextUtility
{
///
/// 该 utility 不需要在初始化阶段执行额外逻辑。
/// 首次加载已经由 在 utility 初始化前完成。
///
protected override void OnInit()
{
}
///
/// 架构销毁时释放 bootstrap 资源,确保热重载监听句柄不会泄漏到架构生命周期之外。
///
protected override void OnDestroy()
{
bootstrap.Dispose();
}
}
}