using System.Collections.Concurrent; using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.versioning; using GFramework.Core.extensions; using GFramework.Core.logging; using GFramework.Core.model; using GFramework.Game.Abstractions.data; using GFramework.Game.Abstractions.setting; namespace GFramework.Game.setting; /// /// 设置模型类,用于管理不同类型的应用程序设置部分 /// public class SettingsModel(IDataRepository? repository) : AbstractModel, ISettingsModel where TRepository : class, IDataRepository { private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger(nameof(SettingsModel)); private readonly ConcurrentDictionary _applicators = new(); private readonly ConcurrentDictionary _dataSettings = new(); private readonly ConcurrentDictionary> _migrationCache = new(); private readonly ConcurrentDictionary<(Type type, int from), ISettingsMigration> _migrations = new(); private IDataRepository? _repository = repository; private IDataRepository Repository => _repository ?? throw new InvalidOperationException("Repository is not set"); // ----------------------------- // Data // ----------------------------- /// /// 获取指定类型的设置数据实例,如果不存在则创建新的实例 /// /// 设置数据类型,必须实现ISettingsData接口并提供无参构造函数 /// 指定类型的设置数据实例 public T GetData() where T : class, IResettable, new() { return (T)_dataSettings.GetOrAdd(typeof(T), _ => new T()); } /// /// 获取所有设置数据的枚举集合 /// /// 所有设置数据的枚举集合 public IEnumerable AllData() { return _dataSettings.Values; } // ----------------------------- // Applicator // ----------------------------- /// /// 获取所有设置应用器的枚举集合 /// /// 所有设置应用器的枚举集合 public IEnumerable AllApplicators() { return _applicators.Values; } /// /// 注册设置应用器到模型中 /// /// 设置应用器类型,必须实现IApplyAbleSettings接口 /// 要注册的设置应用器实例 /// 当前设置模型实例,支持链式调用 public ISettingsModel RegisterApplicator(T applicator) where T : class, IApplyAbleSettings { _applicators[typeof(T)] = applicator; return this; } /// /// 获取指定类型的设置应用器实例 /// /// 设置应用器类型,必须实现IApplyAbleSettings接口 /// 指定类型的设置应用器实例,如果不存在则返回null public T? GetApplicator() where T : class, IApplyAbleSettings { return _applicators.TryGetValue(typeof(T), out var app) ? (T)app : null; } // ----------------------------- // Section lookup // ----------------------------- /// /// 尝试获取指定类型的设置节 /// /// 要查找的设置类型 /// 输出参数,找到的设置节实例 /// 如果找到对应类型的设置节则返回true,否则返回false public bool TryGet(Type type, out ISettingsSection section) { if (_dataSettings.TryGetValue(type, out var data)) { section = data; return true; } if (_applicators.TryGetValue(type, out var applicator)) { section = applicator; return true; } section = null!; return false; } // ----------------------------- // Migration // ----------------------------- /// /// 注册设置迁移器到模型中 /// /// 要注册的设置迁移器实例 /// 当前设置模型实例,支持链式调用 public ISettingsModel RegisterMigration(ISettingsMigration migration) { _migrations[(migration.SettingsType, migration.FromVersion)] = migration; return this; } // ----------------------------- // Load / Init // ----------------------------- /// /// 异步初始化设置模型,加载指定类型的设置数据 /// /// 要初始化的设置类型数组 public async Task InitializeAsync(params Type[] settingTypes) { foreach (var type in settingTypes) { if (!typeof(IResettable).IsAssignableFrom(type) || !typeof(IData).IsAssignableFrom(type)) continue; try { var loaded = (ISettingsSection)await Repository.LoadAsync(type); var migrated = MigrateIfNeeded(loaded); _dataSettings[type] = (IResettable)migrated; _migrationCache.TryRemove(type, out _); } catch (Exception ex) { Log.Error($"Failed to load settings for {type.Name}", ex); } } } /// /// 重置指定类型的可重置对象 /// /// 要重置的对象类型,必须是class类型,实现IResettable接口,并具有无参构造函数 public void Reset() where T : class, IResettable, new() { var data = GetData(); data.Reset(); } /// /// 重置所有存储的数据设置对象 /// public void ResetAll() { foreach (var data in _dataSettings.Values) data.Reset(); } /// /// 如果需要的话,对设置节进行版本迁移 /// /// 待检查和迁移的设置节 /// 迁移后的设置节 private ISettingsSection MigrateIfNeeded(ISettingsSection section) { if (section is not IVersioned versioned) return section; var type = section.GetType(); var current = section; if (!_migrationCache.TryGetValue(type, out var versionMap)) { versionMap = _migrations .Where(kv => kv.Key.type == type) .ToDictionary(kv => kv.Key.from, kv => kv.Value); _migrationCache[type] = versionMap; } while (versionMap.TryGetValue(versioned.Version, out var migration)) { current = migration.Migrate(current); versioned = (IVersioned)current; } return current; } /// /// 初始化方法,用于获取设置持久化服务 /// protected override void OnInit() { _repository ??= this.GetUtility()!; } }