GeWuYou c918085ba9 refactor(setting): 移除 SettingsModel 的 IDisposable 接口实现
- 从 SettingsModel 类定义中移除 IDisposable 接口
- 删除 Dispose 方法及其相关实现逻辑
- 移除 _disposed 标记字段和相关的资源清理代码
- 简化类结构,不再需要手动管理资源释放
- 依赖垃圾回收器自动处理内存管理
2026-01-28 12:47:08 +08:00

202 lines
6.9 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.

using System.Collections.Concurrent;
using System.Reflection;
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.setting;
namespace GFramework.Game.setting;
/// <summary>
/// 设置模型类,用于管理不同类型的应用程序设置部分
/// </summary>
public class SettingsModel : AbstractModel, ISettingsModel
{
private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger(nameof(SettingsModel));
private readonly ConcurrentDictionary<Type, IApplyAbleSettings> _applicators = new();
private readonly ConcurrentDictionary<Type, ISettingsData> _dataSettings = new();
private readonly ConcurrentDictionary<Type, MethodInfo> _loadAsyncMethodCache = new();
private readonly ConcurrentDictionary<Type, Dictionary<int, ISettingsMigration>> _migrationCache = new();
private readonly ConcurrentDictionary<(Type type, int from), ISettingsMigration> _migrations = new();
private ISettingsPersistence? _persistence;
// -----------------------------
// Data
// -----------------------------
/// <summary>
/// 获取指定类型的设置数据实例,如果不存在则创建新的实例
/// </summary>
/// <typeparam name="T">设置数据类型必须实现ISettingsData接口并提供无参构造函数</typeparam>
/// <returns>指定类型的设置数据实例</returns>
public T GetData<T>() where T : class, ISettingsData, new()
{
return (T)_dataSettings.GetOrAdd(typeof(T), _ => new T());
}
/// <summary>
/// 获取所有设置数据的枚举集合
/// </summary>
/// <returns>所有设置数据的枚举集合</returns>
public IEnumerable<ISettingsData> AllData()
=> _dataSettings.Values;
// -----------------------------
// Applicator
// -----------------------------
/// <summary>
/// 获取所有设置应用器的枚举集合
/// </summary>
/// <returns>所有设置应用器的枚举集合</returns>
public IEnumerable<IApplyAbleSettings> AllApplicators()
=> _applicators.Values;
/// <summary>
/// 注册设置应用器到模型中
/// </summary>
/// <typeparam name="T">设置应用器类型必须实现IApplyAbleSettings接口</typeparam>
/// <param name="applicator">要注册的设置应用器实例</param>
/// <returns>当前设置模型实例,支持链式调用</returns>
public ISettingsModel RegisterApplicator<T>(T applicator)
where T : class, IApplyAbleSettings
{
_applicators[typeof(T)] = applicator;
return this;
}
/// <summary>
/// 获取指定类型的设置应用器实例
/// </summary>
/// <typeparam name="T">设置应用器类型必须实现IApplyAbleSettings接口</typeparam>
/// <returns>指定类型的设置应用器实例如果不存在则返回null</returns>
public T? GetApplicator<T>() where T : class, IApplyAbleSettings
{
return _applicators.TryGetValue(typeof(T), out var app)
? (T)app
: null;
}
// -----------------------------
// Section lookup
// -----------------------------
/// <summary>
/// 尝试获取指定类型的设置节
/// </summary>
/// <param name="type">要查找的设置类型</param>
/// <param name="section">输出参数,找到的设置节实例</param>
/// <returns>如果找到对应类型的设置节则返回true否则返回false</returns>
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
// -----------------------------
/// <summary>
/// 注册设置迁移器到模型中
/// </summary>
/// <param name="migration">要注册的设置迁移器实例</param>
/// <returns>当前设置模型实例,支持链式调用</returns>
public ISettingsModel RegisterMigration(ISettingsMigration migration)
{
_migrations[(migration.SettingsType, migration.FromVersion)] = migration;
return this;
}
/// <summary>
/// 如果需要的话,对设置节进行版本迁移
/// </summary>
/// <param name="section">待检查和迁移的设置节</param>
/// <returns>迁移后的设置节</returns>
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;
}
// -----------------------------
// Load / Init
// -----------------------------
/// <summary>
/// 异步初始化设置模型,加载指定类型的设置数据
/// </summary>
/// <param name="settingTypes">要初始化的设置类型数组</param>
public async Task InitializeAsync(params Type[] settingTypes)
{
foreach (var type in settingTypes)
{
if (!typeof(ISettingsData).IsAssignableFrom(type) ||
!type.IsClass ||
type.GetConstructor(Type.EmptyTypes) == null)
continue;
try
{
var method = _loadAsyncMethodCache.GetOrAdd(type, t => typeof(ISettingsPersistence)
.GetMethod(nameof(ISettingsPersistence.LoadAsync))!
.MakeGenericMethod(t));
var task = (Task)method.Invoke(_persistence, null)!;
await task;
var loaded = (ISettingsSection)((dynamic)task).Result;
var migrated = MigrateIfNeeded(loaded);
_dataSettings[type] = (ISettingsData)migrated;
_migrationCache.TryRemove(type, out _);
}
catch (Exception ex)
{
Log.Error($"Failed to load settings for {type.Name}: {ex}", ex);
}
}
}
/// <summary>
/// 初始化方法,用于获取设置持久化服务
/// </summary>
protected override void OnInit()
{
_persistence = this.GetUtility<ISettingsPersistence>();
}
}