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