using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Learn.Utils; public class ConfigItemAttribute(string name) : Attribute { public readonly string Name = name; } public interface IConfigItem { public void OnBeforeSave() { } public void OnAfterLoad() { } } public sealed class Configs { private static readonly ConcurrentDictionary Cache = new(); private readonly ConcurrentDictionary _configObjects = new(); private readonly ConcurrentDictionary _configs = new(); public string ConfigPath { get; set; } = string.Empty; private static string GetConfigItemName(Type type) { if (Cache.TryGetValue(type, out var name)) return name; name = type.Name; if(type.GetCustomAttribute(typeof(ConfigItemAttribute)) is ConfigItemAttribute info) { name = string.IsNullOrEmpty(info.Name) ? type.Name : info.Name; } Cache[type] = name; return name; } /// /// 获取配置项对象 /// /// 配置项类 /// 获取的配置项对象是单例的 /// 配置项对象 public T Get() where T : class, IConfigItem, new() { var name = GetConfigItemName(typeof(T)); if (_configObjects.TryGetValue(name, out var value)) { return (T) value; } T result; if (_configs.TryGetValue(name, out var jObject)) { result = jObject.ToObject(); result.OnAfterLoad(); } else { result = new T(); } _configObjects[name] = result; return result; } /// /// 重置某个配置项。重置完后再取就是一个新的配置项 /// /// 配置项类 public void Reset() where T : class, IConfigItem, new() { var name = GetConfigItemName(typeof(T)); _configs.TryRemove(name, out _); _configObjects.Remove(name, out _); } /// /// 清空当前配置并重新从文件中加载配置 /// /// 当不存在配置文件路径创建默认配置 /// 加载是否成功。无论是否加载成功,当前配置都会被清空 public bool Load(bool createDefaultIfNotExist) { _configs.Clear(); _configObjects.Clear(); if (string.IsNullOrEmpty(ConfigPath)) { return false; } if (!File.Exists(ConfigPath)) { if (!createDefaultIfNotExist) return false; if (!CreateEmptyConfig(ConfigPath)) return false; } try { var configJson = File.ReadAllText(ConfigPath); var config = JObject.Parse(configJson); foreach (var kv in config) { _configs[kv.Key] = kv.Value.ToObject(); } } catch (Exception) { return false; } return true; } /// /// 将当前配置保存到文件中 /// /// public bool Save() { if (string.IsNullOrEmpty(ConfigPath)) return false; try { foreach (var config in _configObjects) { config.Value.OnBeforeSave(); _configs[config.Key] = JObject.FromObject(config.Value); } File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(_configs, Formatting.Indented)); } catch (Exception) { return false; } return true; } private static bool CreateEmptyConfig(string filePath) { var configItemTypes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(assembly => { try { return assembly.GetTypes(); } catch (Exception) { return Array.Empty(); } }) .Where(type => type.IsClass && !type.IsAbstract && typeof(IConfigItem).IsAssignableFrom(type)) .ToList(); var configs = new Dictionary(); foreach (var type in configItemTypes) { var name = GetConfigItemName(type); var item = (IConfigItem) Activator.CreateInstance(type); item.OnBeforeSave(); configs[name] = item; } try { File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented)); } catch (Exception) { return false; } return true; } }