using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace BangumiRenamer.Utils; public class ConfigItemAttribute : System.Attribute { public string Name; public ConfigItemAttribute(string name) { Name = name; } } public interface IConfigItem; public class Config(string configPath) { private static readonly Lazy _lazy = new (() => { var config = new Config("config.json"); config.ReLoad(); return config; }); public static Config Default => _lazy.Value; private static readonly Dictionary Cache = new(); private readonly Dictionary _configObjects = new(); private readonly Dictionary _configs = new(); 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(); } else { result = new T(); } _configObjects[name] = result; return result; } public void Reset() where T : class, IConfigItem, new() { var name = GetConfigItemName(typeof(T)); _configs.Remove(name); _configObjects.Remove(name); } public void Clear() { _configs.Clear(); _configObjects.Clear(); } public void ReLoad() { _configs.Clear(); _configObjects.Clear(); if (!File.Exists(configPath)) return; var configJson = File.ReadAllText(configPath); var config = JObject.Parse(configJson); foreach (var kv in config) { _configs[kv.Key] = kv.Value.ToObject(); } } public void Save() { foreach (var config in _configObjects) { _configs[config.Key] = JObject.FromObject(config.Value); } File.WriteAllText(configPath, JsonConvert.SerializeObject(_configs, Formatting.Indented)); } public static void CreateEmptyConfig() { var configItemTypes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(assembly => { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException) { 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); configs[name] = JObject.FromObject(Activator.CreateInstance(type)); } File.WriteAllText("config_default.json", JsonConvert.SerializeObject(configs, Formatting.Indented)); } }