using GFramework.Core.Abstractions.storage;
using GFramework.Core.extensions;
using GFramework.Core.utility;
using GFramework.Game.Abstractions.setting;
using GFramework.Game.setting.events;
namespace GFramework.Game.setting;
///
/// 设置持久化服务类,负责处理设置数据的加载、保存、删除等操作
///
public class SettingsPersistence : AbstractContextUtility, ISettingsPersistence
{
private IStorage _storage = null!;
///
/// 异步加载指定类型的设置数据
///
/// 设置数据类型,必须实现ISettingsData接口
/// 如果存在则返回存储的设置数据,否则返回新创建的实例
public async Task LoadAsync() where T : class, ISettingsData, new()
{
var key = GetKey();
if (await _storage.ExistsAsync(key))
{
var result = await _storage.ReadAsync(key);
this.SendEvent(new SettingsLoadedEvent(result));
return result;
}
var newSettings = new T();
this.SendEvent(new SettingsLoadedEvent(newSettings));
return newSettings;
}
///
/// 异步保存设置数据到存储中
///
/// 设置数据类型,必须实现ISettingsData接口
/// 要保存的设置数据实例
public async Task SaveAsync(T section) where T : class, ISettingsData
{
var key = GetKey();
await _storage.WriteAsync(key, section);
this.SendEvent(new SettingsSavedEvent(section));
}
///
/// 检查指定类型的设置数据是否存在
///
/// 设置数据类型,必须实现ISettingsData接口
/// 如果存在返回true,否则返回false
public async Task ExistsAsync() where T : class, ISettingsData
{
var key = GetKey();
return await _storage.ExistsAsync(key);
}
///
/// 异步删除指定类型的设置数据
///
/// 设置数据类型,必须实现ISettingsData接口
public async Task DeleteAsync() where T : class, ISettingsData
{
var key = GetKey();
_storage.Delete(key);
this.SendEvent(new SettingsDeletedEvent(typeof(T)));
await Task.CompletedTask;
}
///
/// 异步保存所有设置数据到存储中
///
/// 包含所有设置数据的可枚举集合
public async Task SaveAllAsync(IEnumerable allData)
{
var dataList = allData.ToList();
foreach (var data in dataList)
{
var type = data.GetType();
var key = GetKey(type);
await _storage.WriteAsync(key, data);
}
this.SendEvent(new SettingsBatchSavedEvent(dataList));
}
///
/// 异步加载所有已知类型的设置数据
///
/// 已知设置数据类型的集合
/// 类型与对应设置数据的字典映射
public async Task> LoadAllAsync(IEnumerable knownTypes)
{
var result = new Dictionary();
var allSettings = new List();
foreach (var type in knownTypes)
{
var key = GetKey(type);
if (!await _storage.ExistsAsync(key)) continue;
// 使用反射调用泛型方法
var method = typeof(IStorage)
.GetMethod(nameof(IStorage.ReadAsync))!
.MakeGenericMethod(type);
var task = (Task)method.Invoke(_storage, [key])!;
await task;
var loaded = (ISettingsData)((dynamic)task).Result;
result[type] = loaded;
allSettings.Add(loaded);
}
this.SendEvent(new SettingsAllLoadedEvent(allSettings));
return result;
}
public async Task ResetAsync() where T : class, ISettingsData, new()
{
var type = typeof(T);
var key = GetKey(type);
T oldSettings;
if (await _storage.ExistsAsync(key))
{
oldSettings = await _storage.ReadAsync(key);
}
else
{
oldSettings = new T();
}
var newSettings = new T();
await _storage.WriteAsync(key, newSettings);
this.SendEvent(new SettingsResetEvent(oldSettings, newSettings));
return newSettings;
}
public async Task ResetAllAsync()
{
var knownTypes = new List();
var audioSettings = await LoadAllAsync(knownTypes);
var allNewSettings = new List();
foreach (var kvp in audioSettings)
{
var type = kvp.Key;
var key = GetKey(type);
var newSettings = Activator.CreateInstance(type) as ISettingsSection;
if (newSettings is null) continue;
await _storage.WriteAsync(key, newSettings);
allNewSettings.Add(newSettings);
}
this.SendEvent(new SettingsResetAllEvent(allNewSettings));
}
protected override void OnInit()
{
_storage = this.GetUtility()!;
}
///
/// 获取指定类型的存储键名
///
/// 设置数据类型
/// 格式为"Settings_类型名称"的键名
private static string GetKey() where T : ISettingsData
=> GetKey(typeof(T));
///
/// 获取指定类型的存储键名
///
/// 设置数据类型
/// 格式为"Settings_类型名称"的键名
private static string GetKey(Type type)
=> $"Settings_{type.Name}";
}