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);
}
}
}
}
}