From a29a484834888f20e886910b2bc806cbfeab09fd Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Tue, 27 Jan 2026 22:38:49 +0800
Subject: [PATCH] =?UTF-8?q?refactor(setting):=20=E4=BC=98=E5=8C=96?=
=?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=A8=A1=E5=9E=8B=E7=9A=84=E5=B9=B6=E5=8F=91?=
=?UTF-8?q?=E5=AE=89=E5=85=A8=E6=80=A7=E5=92=8C=E6=80=A7=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 将字典集合替换为ConcurrentDictionary以提高并发安全性
- 添加方法缓存机制减少反射调用开销
- 实现迁移缓存避免重复查询操作
- 增加异步加载异常处理和日志记录
- 实现IDisposable接口添加资源清理功能
- 优化GetOrAdd方法简化数据获取逻辑
---
GFramework.Game/setting/SettingsModel.cs | 92 +++++++++++++++++-------
1 file changed, 66 insertions(+), 26 deletions(-)
diff --git a/GFramework.Game/setting/SettingsModel.cs b/GFramework.Game/setting/SettingsModel.cs
index 4f9f7f3..17fb299 100644
--- a/GFramework.Game/setting/SettingsModel.cs
+++ b/GFramework.Game/setting/SettingsModel.cs
@@ -1,5 +1,9 @@
-using GFramework.Core.Abstractions.versioning;
+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;
@@ -8,14 +12,24 @@ namespace GFramework.Game.setting;
///
/// 设置模型类,用于管理不同类型的应用程序设置部分
///
-public class SettingsModel : AbstractModel, ISettingsModel
+public class SettingsModel : AbstractModel, ISettingsModel, IDisposable
{
- private readonly Dictionary _applicators = new();
- private readonly Dictionary _dataSettings = new();
- private readonly Dictionary<(Type type, int from), ISettingsMigration> _migrations = new();
-
+ 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 bool _disposed;
private ISettingsPersistence? _persistence;
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+
// -----------------------------
// Data
// -----------------------------
@@ -27,13 +41,7 @@ public class SettingsModel : AbstractModel, ISettingsModel
/// 指定类型的设置数据实例
public T GetData() where T : class, ISettingsData, new()
{
- var type = typeof(T);
- if (_dataSettings.TryGetValue(type, out var data))
- return (T)data;
-
- var created = new T();
- _dataSettings[type] = created;
- return created;
+ return (T)_dataSettings.GetOrAdd(typeof(T), _ => new T());
}
///
@@ -135,7 +143,16 @@ public class SettingsModel : AbstractModel, ISettingsModel
var type = section.GetType();
var current = section;
- while (_migrations.TryGetValue((type, versioned.Version), out var migration))
+ 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;
@@ -144,6 +161,7 @@ public class SettingsModel : AbstractModel, ISettingsModel
return current;
}
+
// -----------------------------
// Load / Init
// -----------------------------
@@ -161,20 +179,24 @@ public class SettingsModel : AbstractModel, ISettingsModel
type.GetConstructor(Type.EmptyTypes) == null)
continue;
- // Load()
- var method = typeof(ISettingsPersistence)
- .GetMethod(nameof(ISettingsPersistence.LoadAsync))!
- .MakeGenericMethod(type);
+ 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 task = (Task)method.Invoke(_persistence, null)!;
+ await task;
- var loaded = (ISettingsSection)((dynamic)task).Result;
-
- // ★ 关键:迁移
- var migrated = MigrateIfNeeded(loaded);
-
- _dataSettings[type] = (ISettingsData)migrated;
+ 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);
+ }
}
}
@@ -185,4 +207,22 @@ public class SettingsModel : AbstractModel, ISettingsModel
{
_persistence = this.GetUtility();
}
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed) return;
+ if (disposing)
+ {
+ // 清理托管资源
+ _dataSettings.Clear();
+ _applicators.Clear();
+ _migrations.Clear();
+ _migrationCache.Clear();
+ _loadAsyncMethodCache.Clear();
+ }
+
+ // 清理非托管资源(如果有)
+
+ _disposed = true;
+ }
}
\ No newline at end of file