From 44ab301c24189a15384d022f2d43fbd3fb141872 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 28 Nov 2024 07:23:29 +0100 Subject: [PATCH] refactor settings load/save - load using LINUQ - load on child settings on demond - prevent error when plugin has been removed - prevent settings loose when plugin has been removed --- Pilz.Configuration/ISettings.cs | 5 +- Pilz.Configuration/Settings.cs | 69 ++++++++++++++++++++++++--- Pilz.Configuration/SettingsManager.cs | 16 +++++-- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/Pilz.Configuration/ISettings.cs b/Pilz.Configuration/ISettings.cs index e84394f..a53e50b 100644 --- a/Pilz.Configuration/ISettings.cs +++ b/Pilz.Configuration/ISettings.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Newtonsoft.Json; +using System.Collections.Generic; namespace Pilz.Configuration; @@ -7,4 +8,6 @@ public interface ISettings IReadOnlyCollection Childs { get; } T Get() where T : IChildSettings, ISettingsIdentifier; void Reset(); + string Save(JsonSerializerSettings serializer); + bool Load(JsonSerializerSettings serializer, string raw); } \ No newline at end of file diff --git a/Pilz.Configuration/Settings.cs b/Pilz.Configuration/Settings.cs index ccc31fe..9a40c87 100644 --- a/Pilz.Configuration/Settings.cs +++ b/Pilz.Configuration/Settings.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; @@ -6,21 +7,29 @@ namespace Pilz.Configuration; public class Settings : ISettings { - [JsonProperty(nameof(Settings))] - protected readonly Dictionary mySettings = []; + protected readonly Dictionary settingsJson = []; + protected readonly Dictionary settings = []; + protected JsonSerializerSettings serializerSettings; - [JsonIgnore] - public IReadOnlyCollection Childs => mySettings.Values; + public IReadOnlyCollection Childs => settings.Values; public T Get() where T : IChildSettings, ISettingsIdentifier { - if (mySettings.TryGetValue(T.Identifier, out IChildSettings valueExisting) && valueExisting is T settingsExisting) + if (settings.TryGetValue(T.Identifier, out var valueExisting) && valueExisting is T settingsExisting) return settingsExisting; + if (settingsJson.TryGetValue(T.Identifier, out var valueRaw) + && valueRaw.ToObject(JsonSerializer.CreateDefault(serializerSettings)) is T settingsDeserialized) + { + if (!settings.TryAdd(T.Identifier, settingsDeserialized)) + settings[T.Identifier] = settingsDeserialized; + return settingsDeserialized; + } + if (Activator.CreateInstance() is T settingsNew) { settingsNew.Reset(); - mySettings.Add(T.Identifier, settingsNew); + settings.Add(T.Identifier, settingsNew); return settingsNew; } @@ -29,7 +38,53 @@ public class Settings : ISettings public void Reset() { - foreach (var s in mySettings.Values) + foreach (var s in settings.Values) s.Reset(); } + + public 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 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; + } } \ No newline at end of file diff --git a/Pilz.Configuration/SettingsManager.cs b/Pilz.Configuration/SettingsManager.cs index b4e5f0b..80d48f1 100644 --- a/Pilz.Configuration/SettingsManager.cs +++ b/Pilz.Configuration/SettingsManager.cs @@ -97,27 +97,33 @@ public class SettingsManager : ISettingsManager Instance.Reset(); } + protected virtual ISettings CreateInstance() + { + return new Settings(); + } + protected virtual void CreateNewInstance() { - defaultInstance = new Settings(); + defaultInstance = CreateInstance(); defaultInstance.Reset(); } protected virtual void LoadInternal() { - defaultInstance = JsonConvert.DeserializeObject(File.ReadAllText(ConfigFilePath), CreateJsonSerializerSettings()); + defaultInstance = CreateInstance(); + defaultInstance.Load(CreateJsonSerializerSettings(), File.ReadAllText(ConfigFilePath)); } protected virtual void SaveInternal() { SavingSettings?.Invoke(this, EventArgs.Empty); - File.WriteAllText(ConfigFilePath, JsonConvert.SerializeObject(defaultInstance, CreateJsonSerializerSettings())); + File.WriteAllText(ConfigFilePath, defaultInstance.Save(CreateJsonSerializerSettings())); SavedSettings?.Invoke(this, EventArgs.Empty); } - protected virtual JsonSerializerSettings CreateJsonSerializerSettings() + public virtual JsonSerializerSettings CreateJsonSerializerSettings() { - return new JsonSerializerSettings() + return new JsonSerializerSettings { Formatting = Formatting.Indented, TypeNameHandling = TypeNameHandling.Auto,