2026-02-04 22:10:16 +01:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Xml.Linq;
|
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
|
|
|
|
|
|
|
namespace ImageCatalog;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Modern parameter storage service using XML for persistence.
|
|
|
|
|
|
/// Thread-safe key-value store for application settings.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class ParametriSetup
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
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)
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
_logger = logger ?? Microsoft.Extensions.Logging.Abstractions.NullLogger<ParametriSetup>.Instance;
|
|
|
|
|
|
NomeFileSetup = fileSetup;
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(fileSetup))
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
CaricaParametriSetup();
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
2026-02-04 22:10:16 +01:00
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Loads settings from the XML file.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void CaricaParametriSetup()
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (_lock)
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2025-09-19 10:56:39 +02:00
|
|
|
|
if (string.IsNullOrEmpty(NomeFileSetup) || !File.Exists(NomeFileSetup))
|
|
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
_parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
2025-09-19 10:56:39 +02:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
try
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
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);
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
2026-02-04 22:10:16 +01:00
|
|
|
|
catch (Exception ex)
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
_logger.LogError(ex, "Failed to load settings from {FilePath}", NomeFileSetup);
|
|
|
|
|
|
_parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-04 22:10:16 +01:00
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <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.");
|
2025-09-19 10:56:39 +02:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
lock (_lock)
|
|
|
|
|
|
{
|
2021-03-04 10:44:09 +01:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
// 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);
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
2026-02-04 22:10:16 +01:00
|
|
|
|
catch (Exception ex)
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
_logger.LogError(ex, "Failed to save settings to {FilePath}", NomeFileSetup);
|
|
|
|
|
|
throw;
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-04 22:10:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <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
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
"TRUE" or "OK" or "SI" or "1" or "YES" or "VERO" => true,
|
|
|
|
|
|
_ => false
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <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))
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
return (T)(object)LeggiParametroBoolean(nomeParametro);
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
return (T)Convert.ChangeType(raw, targetType, CultureInfo.InvariantCulture);
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
2026-02-04 22:10:16 +01:00
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogWarning(ex, "Failed to convert parameter {ParameterName} to {TypeName}, using default value",
|
|
|
|
|
|
nomeParametro, typeof(T).Name);
|
|
|
|
|
|
return defaultValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <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)
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
return _parameters.ContainsKey(nomeParametro);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <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);
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
2026-02-04 22:10:16 +01:00
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets all parameter names.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>Collection of parameter names.</returns>
|
|
|
|
|
|
public IReadOnlyCollection<string> GetParameterNames()
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (_lock)
|
2021-03-04 10:44:09 +01:00
|
|
|
|
{
|
2026-02-04 22:10:16 +01:00
|
|
|
|
return _parameters.Keys.ToList();
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-19 10:56:39 +02:00
|
|
|
|
|
2026-02-04 22:10:16 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Clears all parameters.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void ClearAll()
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (_lock)
|
|
|
|
|
|
{
|
|
|
|
|
|
_parameters.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-04 10:44:09 +01:00
|
|
|
|
}
|