107 lines
4.2 KiB
C#
107 lines
4.2 KiB
C#
using FSI.Lib.EasyEncryption;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
|
|
namespace FSI.Lib.WinSettings
|
|
{
|
|
/// <summary>
|
|
/// Provides an abstract base class for specialized settings classes.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Specialized classes should inherit from this class and implement specific storage and
|
|
/// retrieval logic for each settings by overriding the
|
|
/// <see cref="OnSaveSettings(IEnumerable{Setting})"/> and
|
|
/// <see cref="OnLoadSettings(IEnumerable{Setting})"/> methods.
|
|
/// </para>
|
|
/// <para>
|
|
/// 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.
|
|
/// </para>
|
|
/// </remarks>
|
|
public abstract class Settings
|
|
{
|
|
private IEnumerable<Setting> SettingsList { get; }
|
|
|
|
/// <summary>
|
|
/// Abstract method called when the settings should be saved. Allows
|
|
/// the derived class to save those settings in a specialized way.
|
|
/// </summary>
|
|
/// <param name="settings">The list of settings to be saved.</param>
|
|
public abstract void OnSaveSettings(IEnumerable<Setting> settings);
|
|
|
|
/// <summary>
|
|
/// Abstract method called when the settings sould be loaded. Allows
|
|
/// the derived class to load those settings in a specialized way.
|
|
/// </summary>
|
|
/// <param name="settings">The list of settings to be loaded.</param>
|
|
public abstract void OnLoadSettings(IEnumerable<Setting> settings);
|
|
|
|
/// <summary>
|
|
/// Gets the <c>Encryption</c> instance associated with this <c>Settings</c>
|
|
/// instance.
|
|
/// </summary>
|
|
[ExcludedSetting]
|
|
public Encryption Encryption { get; }
|
|
|
|
/// <summary>
|
|
/// Constructs a new <see cref="Settings"></see> instance.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// An exception is thrown if password is null but one or more properties have the
|
|
/// <see cref="EncryptedSettingAttribute"></see> attribute.
|
|
/// </remarks>
|
|
/// <param name="password">Encryption password. Can be <c>null</c> if no
|
|
/// properties have the <see cref="EncryptedSettingAttribute"></see>
|
|
/// attribute.</param>
|
|
public Settings(string password = null)
|
|
{
|
|
if (password == null)
|
|
password = GetType().Namespace.ToString();
|
|
|
|
SettingsList = BuildSettingsList();
|
|
Encryption = password != null ?
|
|
new Encryption(password, EncryptionAlgorithm.TripleDes) :
|
|
null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves all settings.
|
|
/// </summary>
|
|
public void Save()
|
|
{
|
|
OnSaveSettings(SettingsList);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads all settings.
|
|
/// </summary>
|
|
public void Load()
|
|
{
|
|
OnLoadSettings(SettingsList);
|
|
}
|
|
|
|
private IEnumerable<Setting> 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|