using System.Collections.Concurrent; using System.IO; using System.Text.Json; using GFramework.Core.Abstractions.Configuration; using GFramework.Core.Abstractions.Events; using GFramework.Core.Abstractions.Logging; using GFramework.Core.Logging; namespace GFramework.Core.Configuration; /// /// 配置管理器实现,提供线程安全的配置存储和访问 /// 线程安全:所有公共方法都是线程安全的 /// public class ConfigurationManager : IConfigurationManager { /// /// Key 参数验证错误消息常量 /// private const string KeyCannotBeNullOrEmptyMessage = "Key cannot be null or whitespace."; /// /// Path 参数验证错误消息常量 /// private const string PathCannotBeNullOrEmptyMessage = "Path cannot be null or whitespace."; /// /// JSON 参数验证错误消息常量 /// private const string JsonCannotBeNullOrEmptyMessage = "JSON cannot be null or whitespace."; /// /// 配置存储字典(线程安全) /// private readonly ConcurrentDictionary _configs = new(); private readonly ILogger _logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(ConfigurationManager)); /// /// 用于保护监听器列表的锁 /// private readonly object _watcherLock = new(); /// /// 配置监听器字典(线程安全) /// 键:配置键,值:监听器列表 /// private readonly ConcurrentDictionary> _watchers = new(); /// /// 获取配置数量 /// public int Count => _configs.Count; /// /// 获取指定键的配置值 /// public T? GetConfig(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException(KeyCannotBeNullOrEmptyMessage, nameof(key)); if (_configs.TryGetValue(key, out var value)) { return ConvertValue(value); } return default; } /// /// 获取指定键的配置值,如果不存在则返回默认值 /// public T GetConfig(string key, T defaultValue) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException(KeyCannotBeNullOrEmptyMessage, nameof(key)); if (_configs.TryGetValue(key, out var value)) { return ConvertValue(value); } return defaultValue; } /// /// 设置指定键的配置值 /// public void SetConfig(string key, T value) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException(KeyCannotBeNullOrEmptyMessage, nameof(key)); // 先获取旧值,以便正确检测变更 _configs.TryGetValue(key, out var oldValue); // 更新配置值 _configs[key] = value!; // 只有在值真正变化时才触发监听器 if (!EqualityComparer.Default.Equals(oldValue, value)) { NotifyWatchers(key, value); } } /// /// 检查指定键的配置是否存在 /// public bool HasConfig(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException(KeyCannotBeNullOrEmptyMessage, nameof(key)); return _configs.ContainsKey(key); } /// /// 移除指定键的配置 /// public bool RemoveConfig(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException(KeyCannotBeNullOrEmptyMessage, nameof(key)); var removed = _configs.TryRemove(key, out _); if (removed) { // 移除该键的所有监听器(使用锁保护) lock (_watcherLock) { _watchers.TryRemove(key, out _); } } return removed; } /// /// 清空所有配置 /// public void Clear() { _configs.Clear(); // 清空监听器(使用锁保护) lock (_watcherLock) { _watchers.Clear(); } } /// /// 监听指定键的配置变化 /// public IUnRegister WatchConfig(string key, Action onChange) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException(KeyCannotBeNullOrEmptyMessage, nameof(key)); if (onChange == null) throw new ArgumentNullException(nameof(onChange)); lock (_watcherLock) { if (!_watchers.TryGetValue(key, out var watchers)) { watchers = new List(); _watchers[key] = watchers; } watchers.Add(onChange); } return new ConfigWatcherUnRegister(() => UnwatchConfig(key, onChange)); } /// /// 从 JSON 字符串加载配置 /// public void LoadFromJson(string json) { if (string.IsNullOrWhiteSpace(json)) throw new ArgumentException(JsonCannotBeNullOrEmptyMessage, nameof(json)); var dict = JsonSerializer.Deserialize>(json); if (dict == null) return; foreach (var kvp in dict) { _configs[kvp.Key] = kvp.Value; } } /// /// 将配置保存为 JSON 字符串 /// public string SaveToJson() { var dict = _configs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); return JsonSerializer.Serialize(dict, new JsonSerializerOptions { WriteIndented = true }); } /// /// 从文件加载配置 /// public void LoadFromFile(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); if (!File.Exists(path)) throw new FileNotFoundException($"Configuration file not found: {path}"); var json = File.ReadAllText(path); LoadFromJson(json); } /// /// 将配置保存到文件 /// public void SaveToFile(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); var directory = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var json = SaveToJson(); File.WriteAllText(path, json); } /// /// 获取所有配置键 /// public IEnumerable GetAllKeys() { return _configs.Keys.ToList(); } /// /// 取消监听指定键的配置变化 /// private void UnwatchConfig(string key, Action onChange) { lock (_watcherLock) { if (_watchers.TryGetValue(key, out var watchers)) { watchers.Remove(onChange); if (watchers.Count == 0) { _watchers.TryRemove(key, out _); } } } } /// /// 通知监听器配置已变化 /// private void NotifyWatchers(string key, T newValue) { List? watchersCopy = null; lock (_watcherLock) { if (_watchers.TryGetValue(key, out var watchers)) { watchersCopy = new List(watchers); } } if (watchersCopy == null) return; foreach (var watcher in watchersCopy) { try { if (watcher is Action typedWatcher) { typedWatcher(newValue); } } catch (Exception ex) { // 防止监听器异常影响其他监听器 _logger.Error($"Error in config watcher for key '{key}'", ex); } } } /// /// 转换配置值到目标类型 /// private static T ConvertValue(object value) { if (value is T typedValue) { return typedValue; } // 处理 JsonElement 类型 if (value is JsonElement jsonElement) { return JsonSerializer.Deserialize(jsonElement.GetRawText())!; } // 尝试类型转换 try { return (T)Convert.ChangeType(value, typeof(T)); } catch { return default!; } } }