From 76a8b140f1ed6c37d71afc45f438bc2a71917ab7 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Wed, 28 Jan 2026 20:36:24 +0800
Subject: [PATCH] =?UTF-8?q?refactor(setting):=20=E5=B0=86=E8=AE=BE?=
=?UTF-8?q?=E7=BD=AE=E6=8C=81=E4=B9=85=E5=8C=96=E5=8A=9F=E8=83=BD=E6=95=B4?=
=?UTF-8?q?=E5=90=88=E5=88=B0=E6=95=B0=E6=8D=AE=E4=BB=93=E5=BA=93=E4=B8=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除独立的SettingsPersistence类,将其功能合并到DataRepository
- 在DataRepository中新增基于Type参数的异步加载方法
- 修改SettingsModel以使用IDataRepository替代ISettingsPersistence
- 更新SettingsModel为泛型类并注入数据仓库依赖
- 将ISettingsSection接口继承IData接口
- 删除ISettingsPersistence接口定义
---
.../data/IDataRepository.cs | 13 +-
.../setting/ISettingsPersistence.cs | 35 ------
.../setting/ISettingsSection.cs | 6 +-
GFramework.Game/data/DataRepository.cs | 36 ++++++
GFramework.Game/setting/SettingsModel.cs | 30 ++---
.../setting/SettingsPersistence.cs | 113 ------------------
6 files changed, 65 insertions(+), 168 deletions(-)
delete mode 100644 GFramework.Game.Abstractions/setting/ISettingsPersistence.cs
delete mode 100644 GFramework.Game/setting/SettingsPersistence.cs
diff --git a/GFramework.Game.Abstractions/data/IDataRepository.cs b/GFramework.Game.Abstractions/data/IDataRepository.cs
index a1b3ef0..0077a5b 100644
--- a/GFramework.Game.Abstractions/data/IDataRepository.cs
+++ b/GFramework.Game.Abstractions/data/IDataRepository.cs
@@ -11,12 +11,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+using GFramework.Core.Abstractions.utility;
+
namespace GFramework.Game.Abstractions.data;
///
/// 定义数据仓库接口,提供异步的数据加载、保存、检查存在性和删除操作
///
-public interface IDataRepository
+public interface IDataRepository : IUtility
{
///
/// 异步加载指定类型的数据对象
@@ -25,6 +27,13 @@ public interface IDataRepository
/// 返回加载的数据对象的Task
Task LoadAsync() where T : class, IData, new();
+ ///
+ /// 根据类型异步加载数据
+ ///
+ /// 要加载的数据类型
+ /// 异步操作任务,返回实现IData接口的数据对象
+ Task LoadAsync(Type type);
+
///
/// 异步保存指定的数据对象
///
@@ -50,5 +59,7 @@ public interface IDataRepository
///
/// 批量保存多个数据
///
+ /// 要保存的数据列表,实现IData接口的对象集合
+ /// 异步操作任务
Task SaveAllAsync(IEnumerable dataList);
}
\ No newline at end of file
diff --git a/GFramework.Game.Abstractions/setting/ISettingsPersistence.cs b/GFramework.Game.Abstractions/setting/ISettingsPersistence.cs
deleted file mode 100644
index 00280ae..0000000
--- a/GFramework.Game.Abstractions/setting/ISettingsPersistence.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using GFramework.Core.Abstractions.utility;
-
-namespace GFramework.Game.Abstractions.setting;
-
-///
-/// 设置持久化接口
-/// 定义了设置数据的异步加载、保存、检查存在性和删除操作
-///
-public interface ISettingsPersistence : IContextUtility
-{
- ///
- /// 异步加载指定类型的设置数据
- ///
- Task LoadAsync() where T : class, IResettable, new();
-
- ///
- /// 异步保存指定的设置数据
- ///
- Task SaveAsync(T section) where T : class, IResettable;
-
- ///
- /// 异步检查指定类型的设置数据是否存在
- ///
- Task ExistsAsync() where T : class, IResettable;
-
- ///
- /// 异步删除指定类型的设置数据
- ///
- Task DeleteAsync() where T : class, IResettable;
-
- ///
- /// 保存所有设置数据
- ///
- Task SaveAllAsync(IEnumerable allData);
-}
\ No newline at end of file
diff --git a/GFramework.Game.Abstractions/setting/ISettingsSection.cs b/GFramework.Game.Abstractions/setting/ISettingsSection.cs
index be480fe..7beb968 100644
--- a/GFramework.Game.Abstractions/setting/ISettingsSection.cs
+++ b/GFramework.Game.Abstractions/setting/ISettingsSection.cs
@@ -1,7 +1,9 @@
-namespace GFramework.Game.Abstractions.setting;
+using GFramework.Game.Abstractions.data;
+
+namespace GFramework.Game.Abstractions.setting;
///
/// 表示游戏设置的一个配置节接口
/// 该接口定义了设置配置节的基本契约,用于管理游戏中的各种配置选项
///
-public interface ISettingsSection;
\ No newline at end of file
+public interface ISettingsSection : IData;
\ No newline at end of file
diff --git a/GFramework.Game/data/DataRepository.cs b/GFramework.Game/data/DataRepository.cs
index 599ad2b..1de64dc 100644
--- a/GFramework.Game/data/DataRepository.cs
+++ b/GFramework.Game/data/DataRepository.cs
@@ -44,6 +44,7 @@ public class DataRepository(IStorage? storage, DataRepositoryOptions? options =
var key = GetKey();
T result;
+ // 检查存储中是否存在指定键的数据
if (await Storage.ExistsAsync(key))
{
result = await Storage.ReadAsync(key);
@@ -53,12 +54,47 @@ public class DataRepository(IStorage? storage, DataRepositoryOptions? options =
result = new T();
}
+ // 如果启用事件功能,则发送数据加载完成事件
if (_options.EnableEvents)
this.SendEvent(new DataLoadedEvent(result));
return result;
}
+ ///
+ /// 异步加载指定类型的数据(通过Type参数)
+ ///
+ /// 要加载的数据类型
+ /// 加载的数据对象
+ public async Task LoadAsync(Type type)
+ {
+ if (!typeof(IData).IsAssignableFrom(type))
+ throw new ArgumentException($"{type.Name} does not implement IData");
+
+ if (!type.IsClass || type.GetConstructor(Type.EmptyTypes) == null)
+ throw new ArgumentException($"{type.Name} must be a class with parameterless constructor");
+
+ var key = GetKey(type);
+
+ IData result;
+ // 检查存储中是否存在指定键的数据
+ if (await Storage.ExistsAsync(key))
+ {
+ result = await Storage.ReadAsync(key);
+ }
+ else
+ {
+ result = (IData)Activator.CreateInstance(type)!;
+ }
+
+ // 如果启用事件功能,则发送数据加载完成事件
+ if (_options.EnableEvents)
+ this.SendEvent(new DataLoadedEvent(result));
+
+ return result;
+ }
+
+
///
/// 异步保存指定类型的数据
///
diff --git a/GFramework.Game/setting/SettingsModel.cs b/GFramework.Game/setting/SettingsModel.cs
index 9c18cb7..86bd2e4 100644
--- a/GFramework.Game/setting/SettingsModel.cs
+++ b/GFramework.Game/setting/SettingsModel.cs
@@ -1,10 +1,10 @@
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.data;
using GFramework.Game.Abstractions.setting;
namespace GFramework.Game.setting;
@@ -12,15 +12,18 @@ namespace GFramework.Game.setting;
///
/// 设置模型类,用于管理不同类型的应用程序设置部分
///
-public class SettingsModel : AbstractModel, ISettingsModel
+public class SettingsModel(IDataRepository? repository)
+ : AbstractModel, ISettingsModel where TRepository : class, IDataRepository
{
- private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger(nameof(SettingsModel));
+ private static readonly ILogger Log =
+ LoggerFactoryResolver.Provider.CreateLogger(nameof(SettingsModel));
+
private readonly ConcurrentDictionary _applicators = new();
private readonly ConcurrentDictionary _dataSettings = new();
- private readonly ConcurrentDictionary _loadAsyncMethodCache = new();
private readonly ConcurrentDictionary> _migrationCache = new();
private readonly ConcurrentDictionary<(Type type, int from), ISettingsMigration> _migrations = new();
- private ISettingsPersistence? _persistence;
+ private IDataRepository? _repository = repository;
+ private IDataRepository Repository => _repository ?? throw new InvalidOperationException("Repository is not set");
// -----------------------------
// Data
@@ -167,36 +170,29 @@ public class SettingsModel : AbstractModel, ISettingsModel
foreach (var type in settingTypes)
{
if (!typeof(IResettable).IsAssignableFrom(type) ||
- !type.IsClass ||
- type.GetConstructor(Type.EmptyTypes) == null)
+ !typeof(IData).IsAssignableFrom(type))
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 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}", ex);
+ Log.Error($"Failed to load settings for {type.Name}", ex);
}
}
}
+
///
/// 初始化方法,用于获取设置持久化服务
///
protected override void OnInit()
{
- _persistence = this.GetUtility();
+ _repository ??= this.GetUtility()!;
}
}
\ No newline at end of file
diff --git a/GFramework.Game/setting/SettingsPersistence.cs b/GFramework.Game/setting/SettingsPersistence.cs
deleted file mode 100644
index 27987b3..0000000
--- a/GFramework.Game/setting/SettingsPersistence.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-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, IResettable, 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, IResettable
- {
- var key = GetKey();
- await _storage.WriteAsync(key, section);
- this.SendEvent(new SettingsSavedEvent(section));
- }
-
- ///
- /// 检查指定类型的设置数据是否存在
- ///
- /// 设置数据类型,必须实现ISettingsData接口
- /// 如果存在返回true,否则返回false
- public async Task ExistsAsync() where T : class, IResettable
- {
- var key = GetKey();
- return await _storage.ExistsAsync(key);
- }
-
- ///
- /// 异步删除指定类型的设置数据
- ///
- /// 设置数据类型,必须实现ISettingsData接口
- public async Task DeleteAsync() where T : class, IResettable
- {
- var key = GetKey();
- await _storage.DeleteAsync(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));
- }
-
- protected override void OnInit()
- {
- _storage = this.GetUtility()!;
- }
-
- ///
- /// 获取指定类型的存储键名
- ///
- /// 设置数据类型
- /// 格式为"Settings_类型名称"的键名
- private static string GetKey() where T : IResettable
- {
- return GetKey(typeof(T));
- }
-
- ///
- /// 获取指定类型的存储键名
- ///
- /// 设置数据类型
- /// 格式为"Settings_类型名称"的键名
- private static string GetKey(Type type)
- {
- return $"Settings_{type.Name}";
- }
-}
\ No newline at end of file