using System; using System.Diagnostics; using System.Linq; using System.Reflection; namespace FSI.Lib.WinSettings { /// /// Represents a single setting for -derived classes. /// public class Setting { private readonly Settings Settings; private readonly PropertyInfo PropertyInfo; private readonly bool Encrypted; /// /// Constructs a new instance of the class. /// /// The class that contains /// this property (setting). /// The for this /// property. /// Indicates whether or not this setting is /// encrypted. public Setting(Settings settings, PropertyInfo propertyInfo, bool encrypted) { Settings = settings; PropertyInfo = propertyInfo; Encrypted = encrypted; } /// /// Gets the name of this setting. /// public string Name => PropertyInfo.Name; /// /// Gets the type of this setting. /// public Type Type => Encrypted ? typeof(string) : PropertyInfo.PropertyType; /// /// Gets the value of this setting. /// /// Returns the value of this setting. public object GetValue() { object value = PropertyInfo.GetValue(Settings); if (value != null && Encrypted && Settings.Encryption != null) return Settings.Encryption.Encrypt(value); return value; } /// /// Sets the value of this setting. /// /// The value this setting should be set to. public void SetValue(object value) { // Leave property value unmodified if no value or error if (value != null) { try { if (Encrypted && Settings.Encryption != null) { // Ecrypted values stored as string if (value is string s) PropertyInfo.SetValue(Settings, Settings.Encryption.Decrypt(s, PropertyInfo.PropertyType)); } else PropertyInfo.SetValue(Settings, Convert.ChangeType(value, Type)); } catch (Exception) { Debug.Assert(false); } } } /// /// Gets this setting's value as a string. /// /// Returns this setting's value as a string. public string GetValueAsString() { object value = GetValue(); if (value == null) return string.Empty; else if (value is byte[] byteArray) return ArrayToString.Encode(byteArray.Select(b => b.ToString()).ToArray()); else if (value is string[] stringArray) return ArrayToString.Encode(stringArray); else return value?.ToString() ?? string.Empty; } /// /// Sets this setting's value from a string. /// /// A string that represents the value this setting should be set to. public void SetValueFromString(string value) { if (value != null) { try { if (Type == typeof(byte[])) SetValue(ArrayToString.Decode(value).Select(s => byte.Parse(s)).ToArray()); else if (Type == typeof(string[])) SetValue(ArrayToString.Decode(value)); else SetValue(value); } catch (Exception) { Debug.Assert(false); } } } } }