using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; namespace Pilz.Configuration; public class Settings : ISettings { protected readonly Dictionary settingsJson = []; protected readonly Dictionary settings = []; protected JsonSerializerSettings serializerSettings; public virtual IReadOnlyCollection Childs => settings.Values; public virtual T Get() where T : ISettingsNode, ISettingsIdentifier { // Find existing one if (settings.TryGetValue(T.Identifier, out var valueExisting) && valueExisting is T settingsExisting) return settingsExisting; // Create new & reset if (Activator.CreateInstance() is T settingsNew) settingsNew.Reset(); else settingsNew = default; // Try deserialize if (settingsJson.TryGetValue(T.Identifier, out var valueRaw)) { var serializer = JsonSerializer.CreateDefault(serializerSettings); // Populate if (settingsNew != null) serializer.Populate(valueRaw.CreateReader(), settingsNew); // Deserialize (fallback) else if (valueRaw.ToObject() is T settingsDeserialized) settingsNew = settingsDeserialized; } // Remember if (settingsNew != null) settings[T.Identifier] = settingsNew; // Return return settingsNew; } public void Reset() { foreach (var s in settings.Values) s.Reset(); } public virtual string Save(JsonSerializerSettings serializerSettings) { this.serializerSettings = serializerSettings; var serializer = JsonSerializer.CreateDefault(serializerSettings); foreach (var kvp in settings) { var raw = JObject.FromObject(kvp.Value, serializer); if (!settingsJson.TryAdd(kvp.Key, raw)) settingsJson[kvp.Key] = raw; } var objList = new JObject(); foreach (var kvp in settingsJson) objList.Add(kvp.Key, kvp.Value); var objSettings = new JObject { { "Settings", objList } }; return objSettings.ToString(serializer.Formatting); } public virtual bool Load(JsonSerializerSettings serializerSettings, string raw) { this.serializerSettings = serializerSettings; var objSettings = JObject.Parse(raw); if (!objSettings.TryGetValue("Settings", out var tokenList) || tokenList is not JObject objList) return false; settingsJson.Clear(); settings.Clear(); foreach (var child in objList) { if (child.Value is not JObject value) continue; settingsJson.Add(child.Key, value); } return true; } protected virtual JToken Serialize(object o, JsonSerializer jsonSerializer) { using JTokenWriter jTokenWriter = new JTokenWriter(); jsonSerializer.Serialize(jTokenWriter, o, o.GetType()); return jTokenWriter.Token; } }