Catalog/imagecatalog/Services/SettingsService.cs
2026-02-04 22:10:16 +01:00

180 lines
7 KiB
C#

using System;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml.Serialization;
using ImageCatalog;
using ImageCatalog_2.Models;
using Microsoft.Extensions.Logging;
namespace ImageCatalog_2.Services
{
/// <summary>
/// Modern settings service that uses DTO with attributes for serialization
/// </summary>
public class SettingsService : ISettingsService
{
private readonly ParametriSetup _parametriSetup;
private readonly ILogger<SettingsService> _logger;
public SettingsService(ParametriSetup parametriSetup, ILogger<SettingsService> logger)
{
_parametriSetup = parametriSetup;
_logger = logger;
}
public Task SaveSettingsAsync(string filePath, object settings)
{
return Task.Run(() =>
{
_parametriSetup.NomeFileSetup = filePath;
// Convert ViewModel to DTO
var dto = ViewModelToDto(settings);
// Use reflection on DTO properties with XmlElement attribute
var properties = typeof(SettingsDto).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in properties)
{
// Get the XmlElement attribute to determine the XML property name
var xmlAttr = prop.GetCustomAttribute<XmlElementAttribute>();
if (xmlAttr == null)
continue; // Skip properties without XmlElement attribute
var xmlName = xmlAttr.ElementName;
var value = prop.GetValue(dto);
_parametriSetup.AggiornaParametro(xmlName, value);
}
_parametriSetup.SalvaParametriSetup();
});
}
public async Task LoadSettingsAsync(string filePath, object settings)
{
// Step 1: Load XML and read into DTO on background thread
var dto = await Task.Run(() =>
{
_parametriSetup.NomeFileSetup = filePath;
_parametriSetup.CaricaParametriSetup();
var loadedDto = new SettingsDto();
var properties = typeof(SettingsDto).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in properties)
{
// Get the XmlElement attribute to determine the XML property name
var xmlAttr = prop.GetCustomAttribute<XmlElementAttribute>();
if (xmlAttr == null)
continue; // Skip properties without XmlElement attribute
var xmlName = xmlAttr.ElementName;
try
{
object value;
if (prop.PropertyType == typeof(string))
{
value = _parametriSetup.LeggiParametroString(xmlName);
}
else if (prop.PropertyType == typeof(bool))
{
value = _parametriSetup.LeggiParametroBoolean(xmlName);
}
else if (prop.PropertyType == typeof(int))
{
value = _parametriSetup.LeggiParametro<int>(xmlName, (int)(prop.GetValue(loadedDto) ?? 0));
}
else if (prop.PropertyType == typeof(double))
{
value = _parametriSetup.LeggiParametro<double>(xmlName, (double)(prop.GetValue(loadedDto) ?? 0.0));
}
else if (prop.PropertyType == typeof(DateTime))
{
var strValue = _parametriSetup.LeggiParametroString(xmlName);
if (DateTime.TryParse(strValue, out var dateValue))
{
value = dateValue;
}
else
{
value = (DateTime)(prop.GetValue(loadedDto) ?? DateTime.Now);
}
}
else
{
continue;
}
prop.SetValue(loadedDto, value);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to read property {XmlName} -> {PropertyName}", xmlName, prop.Name);
}
}
return loadedDto;
});
// Step 2: Apply DTO values to ViewModel on UI thread
DtoToViewModel(dto, settings);
}
/// <summary>
/// Converts DataModel (ViewModel) to SettingsDto
/// </summary>
private SettingsDto ViewModelToDto(object viewModel)
{
var vmType = viewModel.GetType();
var dto = new SettingsDto();
var dtoProps = typeof(SettingsDto).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var dtoProp in dtoProps)
{
// Find matching property in ViewModel by name
var vmProp = vmType.GetProperty(dtoProp.Name, BindingFlags.Public | BindingFlags.Instance);
if (vmProp != null && vmProp.CanRead)
{
var value = vmProp.GetValue(viewModel);
dtoProp.SetValue(dto, value);
}
}
return dto;
}
/// <summary>
/// Copies values from SettingsDto to DataModel (ViewModel)
/// </summary>
private void DtoToViewModel(SettingsDto dto, object viewModel)
{
var vmType = viewModel.GetType();
var dtoProps = typeof(SettingsDto).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var dtoProp in dtoProps)
{
// Find matching property in ViewModel by name
var vmProp = vmType.GetProperty(dtoProp.Name, BindingFlags.Public | BindingFlags.Instance);
if (vmProp != null && vmProp.CanWrite)
{
var value = dtoProp.GetValue(dto);
// Don't update if empty string and current value is not empty
if (dtoProp.PropertyType == typeof(string) && string.IsNullOrEmpty((string)value))
{
var currentValue = vmProp.GetValue(viewModel) as string;
if (!string.IsNullOrEmpty(currentValue))
{
continue;
}
}
vmProp.SetValue(viewModel, value);
_logger.LogDebug("Set {PropertyName} = {Value}", vmProp.Name, value);
}
}
}
}
}