using FSI.Lib.EasyEncryption; using System; using System.Collections.Generic; using System.Reflection; namespace FSI.Lib.WinSettings { /// /// Provides an abstract base class for specialized settings classes. /// /// /// /// Specialized classes should inherit from this class and implement specific storage and /// retrieval logic for each settings by overriding the /// and /// methods. /// /// /// Ultimately, the specialized classes will then be overridden by each application's /// settings class. The public properties in that class will become the settings that /// are saved by classes that derive from this class. /// /// public abstract class Settings { private IEnumerable SettingsList { get; } /// /// Abstract method called when the settings should be saved. Allows /// the derived class to save those settings in a specialized way. /// /// The list of settings to be saved. public abstract void OnSaveSettings(IEnumerable settings); /// /// Abstract method called when the settings sould be loaded. Allows /// the derived class to load those settings in a specialized way. /// /// The list of settings to be loaded. public abstract void OnLoadSettings(IEnumerable settings); /// /// Gets the Encryption instance associated with this Settings /// instance. /// [ExcludedSetting] public Encryption Encryption { get; } /// /// Constructs a new instance. /// /// /// An exception is thrown if password is null but one or more properties have the /// attribute. /// /// Encryption password. Can be null if no /// properties have the /// attribute. public Settings(string password = null) { if (password == null) password = GetType().Namespace.ToString(); SettingsList = BuildSettingsList(); Encryption = password != null ? new Encryption(password, EncryptionAlgorithm.TripleDes) : null; } /// /// Saves all settings. /// public void Save() { OnSaveSettings(SettingsList); } /// /// Loads all settings. /// public void Load() { OnLoadSettings(SettingsList); } private IEnumerable BuildSettingsList() { // Iterate through all public instance properties foreach (PropertyInfo prop in GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) { // Ignore properties with ExcludedSetting attribute if (!Attribute.IsDefined(prop, typeof(ExcludedSettingAttribute))) { // Test for supported data type (same types as for Encryption class) if (!Encryption.IsTypeSupported(prop.PropertyType)) throw new Exception(string.Format("Settings property '{0}' is an unsupported data type '{1}'. Change property type or use ExcludedSetting attribute.", prop.Name, prop.PropertyType.ToString())); bool encrypted = Attribute.IsDefined(prop, typeof(EncryptedSettingAttribute)); if (encrypted && Encryption == null) throw new InvalidOperationException("Encryption password cannot be null if any settings have the EncryptedSetting attribute."); yield return new Setting(this, prop, encrypted); } } } } }