Multiprocotol Terminalprogram (BAT)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MultiTerm/Common/AppSettings/XmlAppSettingsProvider.cs

186 lines
7.3 KiB

using Common.Logging;
using System.Xml.Serialization;
namespace Common.AppSettings;
public class XmlAppSettingsProvider : IAppSettingsProvider
{
private readonly string settingsFilePath;
private readonly XmlSerializer serializer;
private List<AppSetting> settings;
public event EventHandler<LogEntry>? LogWorthyEvent;
public XmlAppSettingsProvider(string settingsFilePath)
{
// check for file path validity
// TODO create file if it does not exist yet
if (String.IsNullOrEmpty(settingsFilePath)) { throw new ArgumentNullException(nameof(settingsFilePath)); }
this.settingsFilePath = settingsFilePath;
this.settings = new List<AppSetting>();
this.serializer = new XmlSerializer(typeof(List<AppSetting>));
}
public void Load()
{
// read file by creating a stream. this will throw an exception when the file does not exist.
using var fileStream = new FileStream(this.settingsFilePath, FileMode.Open);
// deserialize and cast to List if not null
var deserializedObj = this.serializer.Deserialize(fileStream);
if(deserializedObj != null)
{
// create log entry if there were already some settings loaded
if(this.settings.Count > 0)
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Warn, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(Load)}'() deserialization overwrote previously loaded settings."));
}
this.settings = (List<AppSetting>)deserializedObj;
}
else
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Warn, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(Load)}'() deserialization resulted in null object. Did not change loaded settings."));
}
}
public void Save()
{
// TODO write log entries for when something goes wrong
TextWriter writer = new StreamWriter(this.settingsFilePath);
this.serializer.Serialize(writer, this.settings);
writer.Close();
}
public bool WriteSetting(string key, string value)
{
// guard empty key or value
if(String.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key));
if (String.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value));
// get all settings with this key
var foundSettings = this.settings.FindAll(x => x.Key == key);
// check if the key already exists multiple times
if(foundSettings.Count > 1)
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Error, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(WriteSetting)}'() cancelled because {foundSettings.Count} settings with the key '{key}' were found. Expected none or exactly one."));
return false; // cancel
}
// if exactly one is found => remove existing app setting
else if(foundSettings.Count == 1)
{
this.settings.Remove(this.settings.Find(x => x.Key == key)!);
}
// none existing yet => inform via event
else if(foundSettings.Count == 0)
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Info, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(WriteSetting)}'() initialized new setting with key '{key}' and value '{value}'."));
}
// add new setting
this.settings.Add(new AppSetting(key, value));
return true;
}
public bool TryReadSetting(string key, out string value)
{
// guard empty key
if (String.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key));
// get all settings with this key
var foundSettings = this.settings.FindAll(x => x.Key == key);
// too many values found
if (foundSettings.Count > 1)
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Error, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(TryReadSetting)}'() did find {foundSettings.Count} settings with the key '{key}'. Expected only one."));
value = string.Empty;
return false;
}
// no value found
if (foundSettings.Count == 0)
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Error, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(TryReadSetting)}'() did not find a setting with the key '{key}'."));
value = string.Empty;
return false;
}
// extract correct setting when found exactly one
var setting = foundSettings[0];
if(setting.Value != null)
{
value = setting.Value;
}
// if value is null it was probably an empty string or similar => set it to empty string
else
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Warn, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(TryReadSetting)}'() value of retrieved setting with key '{key}' was null. Returned empty string instead."));
value = string.Empty;
}
return true;
}
public bool TryReadSettingOrAddDefault(string key, out string value, string defaultValue)
{
// guard empty key or defaultValue
if (String.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key));
if (String.IsNullOrEmpty(defaultValue)) throw new ArgumentNullException(nameof(defaultValue));
// get all settings with this key
var foundSettings = this.settings.FindAll(x => x.Key == key);
// too many values found
if (foundSettings.Count > 1)
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Error, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(TryReadSettingOrAddDefault)}'() did find {foundSettings.Count} settings with the key '{key}'. Expected only one."));
value = string.Empty;
return false;
}
// no value found => initialize with the default value
if (foundSettings.Count == 0)
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Info, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(TryReadSettingOrAddDefault)}'() did not find a setting with the key '{key}'. Adding setting with value '{defaultValue}'."));
this.WriteSetting(key, defaultValue);
value = defaultValue;
return true;
}
// extract correct setting when found exactly one
var setting = foundSettings[0];
if (setting.Value != null)
{
value = setting.Value;
}
// if value is null it was probably an empty string or similar => set it to empty string
else
{
this.LogWorthyEvent?.Invoke(this, new LogEntry(level: LogLevel.Warn, category: nameof(XmlAppSettingsProvider),
message: $"'{nameof(TryReadSetting)}'() value of retrieved setting with key '{key}' was null. Returned empty string instead."));
value = string.Empty;
}
return true;
}
}