Fixes to settings

This commit is contained in:
MaddoScientisto 2026-02-04 22:10:16 +01:00
commit fc7175c2f7
6 changed files with 628 additions and 267 deletions

View file

@ -1,239 +1,243 @@
using System;
using System.Data;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Extensions.Logging;
namespace ImageCatalog
namespace ImageCatalog;
/// <summary>
/// Modern parameter storage service using XML for persistence.
/// Thread-safe key-value store for application settings.
/// </summary>
public class ParametriSetup
{
public class ParametriSetup
private readonly object _lock = new();
private readonly ILogger<ParametriSetup> _logger;
private Dictionary<string, string> _parameters = new(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Gets or sets the XML file path for settings storage.
/// </summary>
public string? NomeFileSetup { get; set; }
/// <summary>
/// Initializes a new instance with the specified settings file.
/// </summary>
/// <param name="fileSetup">Path to the XML settings file.</param>
/// <param name="logger">Optional logger for diagnostics.</param>
public ParametriSetup(string? fileSetup = null, ILogger<ParametriSetup>? logger = null)
{
private DataSet _elencoParametri;
public string NomeFileSetup { get; set; }
public ParametriSetup(string fileSetup)
_logger = logger ?? Microsoft.Extensions.Logging.Abstractions.NullLogger<ParametriSetup>.Instance;
NomeFileSetup = fileSetup;
if (!string.IsNullOrWhiteSpace(fileSetup))
{
_elencoParametri = new DataSet();
NomeFileSetup = fileSetup;
if (!string.IsNullOrWhiteSpace(fileSetup))
{
CaricaParametriSetup();
}
}
public ParametriSetup() : this(string.Empty)
{
}
public void CaricaParametriSetup()
{
if (string.IsNullOrEmpty(NomeFileSetup) || !File.Exists(NomeFileSetup))
{
_elencoParametri = new DataSet();
return;
}
_elencoParametri = LeggiXmlDataSet("Setup", NomeFileSetup, "Nome");
}
public void SalvaParametriSetup()
{
if (string.IsNullOrWhiteSpace(NomeFileSetup))
throw new InvalidOperationException("NomeFileSetup is not set.");
// overwrite without FileSystem.Kill
_elencoParametri.WriteXml(NomeFileSetup, XmlWriteMode.WriteSchema);
}
// public string LeggiParametroString(string NomeParametro)
// {
// string Risposta = "";
// try
// {
// var LElenco = _elencoParametri.Tables["Setup"].Select("Nome='" + NomeParametro + "'");
// foreach (var LaRiga in LElenco)
// Risposta = LaRiga["Valore"].ToString();
// }
// catch
// {
// Risposta = "";
// }
//
// return Risposta;
// }
//
// public bool LeggiParametroBoolean(string nomeParametro)
// {
// var risposta = "";
// try
// {
// var lElenco = _elencoParametri.Tables["Setup"].Select("Nome='" + nomeParametro + "'");
// foreach (var laRiga in lElenco)
// risposta = laRiga["Valore"].ToString();
// }
// catch
// {
// risposta = "";
// }
//
// switch (risposta.ToUpper() ?? "")
// {
// case "TRUE":
// case "OK":
// case "SI":
// case "1":
// case "YES":
// case "VERO":
// {
// return true;
// }
//
// default:
// {
// return false;
// }
// }
// }
public string LeggiParametroString(string nomeParametro)
{
return GetRow(nomeParametro)?["Valore"]?.ToString() ?? string.Empty;
}
public bool LeggiParametroBoolean(string nomeParametro)
{
var raw = LeggiParametroString(nomeParametro);
return raw?.ToUpperInvariant() switch
{
"TRUE" or "OK" or "SI" or "1" or "YES" or "VERO" => true,
_ => false
};
}
public void AggiornaParametro(string nomeParametro, object valoreParametro)
{
var table = EnsureSetupTable();
var rows = table.Select($"Nome='{nomeParametro.Replace("'", "''")}'");
if (rows.Length == 0)
{
var newRow = table.NewRow();
newRow["Nome"] = nomeParametro;
newRow["Valore"] = valoreParametro?.ToString() ?? string.Empty;
table.Rows.Add(newRow);
}
else
{
rows[0]["Valore"] = valoreParametro?.ToString() ?? string.Empty;
}
}
public T LeggiParametro<T>(string nomeParametro, T defaultValue = default!)
{
var raw = LeggiParametroString(nomeParametro);
if (string.IsNullOrEmpty(raw)) return defaultValue;
try
{
return (T)Convert.ChangeType(raw, typeof(T));
}
catch
{
return defaultValue;
}
}
private static DataSet LeggiXmlDataSet(string nomeTabella, string nomeFileXml, string nomeColonnaChiave = "")
{
var ds = new DataSet();
ds.ReadXml(nomeFileXml);
if (!string.IsNullOrEmpty(nomeColonnaChiave) && ds.Tables.Contains(nomeTabella))
{
var table = ds.Tables[nomeTabella];
if (table.Constraints[nomeColonnaChiave] == null)
{
table.Constraints.Add(nomeColonnaChiave, table.Columns[nomeColonnaChiave], true);
}
}
return ds;
}
private DataTable EnsureSetupTable()
{
if (!_elencoParametri.Tables.Contains("Setup"))
{
var table = new DataTable("Setup");
table.Columns.Add("Nome", typeof(string));
table.Columns.Add("Valore", typeof(string));
_elencoParametri.Tables.Add(table);
}
return _elencoParametri.Tables["Setup"];
}
private DataRow? GetRow(string nomeParametro)
{
if (!_elencoParametri.Tables.Contains("Setup")) return null;
var rows = _elencoParametri.Tables["Setup"]
.Select($"Nome='{nomeParametro.Replace("'", "''")}'");
return rows.FirstOrDefault();
CaricaParametriSetup();
}
}
// public void AggiornaParametro(string NomeParametro, object ValoreParametro)
// {
// try
// {
// if (_elencoParametri.Tables["Setup"] is null)
// {
// var TabellaTmp = new DataTable("Setup");
// DataRow RigaTmp;
// DataColumn LaColonna;
// LaColonna = TabellaTmp.Columns.Add("Nome", Type.GetType("System.String"));
// LaColonna = TabellaTmp.Columns.Add("Valore", Type.GetType("System.String"));
//
// // * Aggiunge alla tabella tutte le righe
// RigaTmp = TabellaTmp.NewRow();
// RigaTmp["Nome"] = NomeParametro;
// RigaTmp["Valore"] = ValoreParametro;
// TabellaTmp.Rows.Add(RigaTmp);
// _elencoParametri.Tables.Add(TabellaTmp);
// }
// else
// {
// var LElenco = _elencoParametri.Tables["Setup"].Select("Nome='" + NomeParametro + "'");
// if (LElenco.Length == 0)
// {
// DataRow LaRiga;
// LaRiga = _elencoParametri.Tables["Setup"].NewRow();
// LaRiga["Nome"] = NomeParametro;
// LaRiga["Valore"] = ValoreParametro;
// _elencoParametri.Tables["Setup"].Rows.Add(LaRiga);
// }
// else
// {
// LElenco[0]["Valore"] = ValoreParametro;
// }
// }
// }
// catch
// {
// }
// }
/// <summary>
/// Loads settings from the XML file.
/// </summary>
public void CaricaParametriSetup()
{
lock (_lock)
{
if (string.IsNullOrEmpty(NomeFileSetup) || !File.Exists(NomeFileSetup))
{
_parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
return;
}
// private static DataSet LeggiXmlDataSet(string NomeTabella, string NomeFileXml, string NomeColonnaChiave = "")
// {
// // * Crea e Legge il dataset dal file xml
// var DataSetXml = new DataSet();
// DataSetXml.ReadXml(NomeFileXml);
//
// // * Aggiunge il campo chiave
// if (!string.IsNullOrEmpty(NomeColonnaChiave))
// {
// DataSetXml.Tables[NomeTabella].Constraints.Add(NomeColonnaChiave, DataSetXml.Tables[NomeTabella].Columns[NomeColonnaChiave], true);
// }
//
// // * Restituisce la risposta
// return DataSetXml;
// }
//}
try
{
var doc = XDocument.Load(NomeFileSetup);
var setupElements = doc.Descendants("Setup");
_parameters = setupElements
.Where(e => e.Element("Nome") != null)
.ToDictionary(
e => e.Element("Nome")!.Value,
e => e.Element("Valore")?.Value ?? string.Empty,
StringComparer.OrdinalIgnoreCase
);
_logger.LogInformation("Loaded {Count} parameters from {FilePath}", _parameters.Count, NomeFileSetup);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to load settings from {FilePath}", NomeFileSetup);
_parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
}
/// <summary>
/// Saves settings to the XML file.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when NomeFileSetup is not set.</exception>
public void SalvaParametriSetup()
{
if (string.IsNullOrWhiteSpace(NomeFileSetup))
throw new InvalidOperationException("NomeFileSetup is not set.");
lock (_lock)
{
try
{
// Ensure directory exists
var directory = Path.GetDirectoryName(NomeFileSetup);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
// Create XML document with DataSet-compatible structure
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("NewDataSet",
_parameters.Select(kvp =>
new XElement("Setup",
new XElement("Nome", kvp.Key),
new XElement("Valore", kvp.Value)
)
)
)
);
doc.Save(NomeFileSetup);
_logger.LogInformation("Saved {Count} parameters to {FilePath}", _parameters.Count, NomeFileSetup);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to save settings to {FilePath}", NomeFileSetup);
throw;
}
}
}
/// <summary>
/// Reads a parameter as a string.
/// </summary>
/// <param name="nomeParametro">Parameter name.</param>
/// <returns>Parameter value or empty string if not found.</returns>
public string LeggiParametroString(string nomeParametro)
{
lock (_lock)
{
return _parameters.TryGetValue(nomeParametro, out var value) ? value : string.Empty;
}
}
/// <summary>
/// Reads a parameter as a boolean.
/// </summary>
/// <param name="nomeParametro">Parameter name.</param>
/// <returns>True if value is truthy (TRUE, OK, SI, 1, YES, VERO), false otherwise.</returns>
public bool LeggiParametroBoolean(string nomeParametro)
{
var raw = LeggiParametroString(nomeParametro);
return raw.ToUpperInvariant() switch
{
"TRUE" or "OK" or "SI" or "1" or "YES" or "VERO" => true,
_ => false
};
}
/// <summary>
/// Updates or creates a parameter.
/// </summary>
/// <param name="nomeParametro">Parameter name.</param>
/// <param name="valoreParametro">Parameter value.</param>
public void AggiornaParametro(string nomeParametro, object? valoreParametro)
{
lock (_lock)
{
_parameters[nomeParametro] = valoreParametro?.ToString() ?? string.Empty;
}
}
/// <summary>
/// Reads a parameter and converts it to the specified type.
/// </summary>
/// <typeparam name="T">Target type.</typeparam>
/// <param name="nomeParametro">Parameter name.</param>
/// <param name="defaultValue">Default value if conversion fails.</param>
/// <returns>Converted value or default value.</returns>
public T LeggiParametro<T>(string nomeParametro, T defaultValue = default!)
{
var raw = LeggiParametroString(nomeParametro);
if (string.IsNullOrEmpty(raw))
return defaultValue;
try
{
// Handle nullable types
var targetType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
// Special handling for common types
if (targetType == typeof(bool))
{
return (T)(object)LeggiParametroBoolean(nomeParametro);
}
return (T)Convert.ChangeType(raw, targetType, CultureInfo.InvariantCulture);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to convert parameter {ParameterName} to {TypeName}, using default value",
nomeParametro, typeof(T).Name);
return defaultValue;
}
}
/// <summary>
/// Checks if a parameter exists.
/// </summary>
/// <param name="nomeParametro">Parameter name.</param>
/// <returns>True if parameter exists, false otherwise.</returns>
public bool ParametroExists(string nomeParametro)
{
lock (_lock)
{
return _parameters.ContainsKey(nomeParametro);
}
}
/// <summary>
/// Removes a parameter.
/// </summary>
/// <param name="nomeParametro">Parameter name.</param>
/// <returns>True if parameter was removed, false if it didn't exist.</returns>
public bool RimuoviParametro(string nomeParametro)
{
lock (_lock)
{
return _parameters.Remove(nomeParametro);
}
}
/// <summary>
/// Gets all parameter names.
/// </summary>
/// <returns>Collection of parameter names.</returns>
public IReadOnlyCollection<string> GetParameterNames()
{
lock (_lock)
{
return _parameters.Keys.ToList();
}
}
/// <summary>
/// Clears all parameters.
/// </summary>
public void ClearAll()
{
lock (_lock)
{
_parameters.Clear();
}
}
}