CtrEditor/Serialization/PropiedadesLocalesManager.cs

128 lines
4.7 KiB
C#

using CtrEditor.ObjetosSim;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Reflection;
namespace CtrEditor.Serialization
{
/// <summary>
/// Clase para gestionar qué propiedades deben ser locales en objetos globales
/// </summary>
public static class PropiedadesLocalesManager
{
// Definición de propiedades por defecto que se guardan localmente para todos los objetos
private static readonly List<string> PropiedadesPorDefecto = new List<string>
{
"Left", "Top", "Ancho", "Alto"
};
// Diccionario que contiene conjuntos de propiedades locales por tipo de objeto
private static readonly Dictionary<Type, List<string>> PropiedadesPorTipo = new Dictionary<Type, List<string>>();
/// <summary>
/// Registra un conjunto de propiedades locales para un tipo específico de objeto
/// </summary>
/// <typeparam name="T">Tipo de objeto (debe heredar de osBase)</typeparam>
/// <param name="propiedades">Lista de nombres de propiedades a registrar como locales</param>
public static void RegistrarPropiedadesParaTipo<T>(List<string> propiedades) where T : osBase
{
PropiedadesPorTipo[typeof(T)] = propiedades;
}
/// <summary>
/// Obtiene la lista de propiedades que deben ser locales para un objeto concreto
/// </summary>
/// <param name="objeto">Objeto del que obtener las propiedades locales</param>
/// <returns>Lista de nombres de propiedades</returns>
public static List<string> ObtenerPropiedadesLocales(osBase objeto)
{
var resultado = new List<string>(PropiedadesPorDefecto);
if (objeto != null && PropiedadesPorTipo.TryGetValue(objeto.GetType(), out var propiedadesExtra))
{
foreach (var prop in propiedadesExtra)
{
if (!resultado.Contains(prop))
resultado.Add(prop);
}
}
return resultado;
}
/// <summary>
/// Crea un objeto dinámico que permite acceder a las propiedades locales de un objeto
/// </summary>
/// <param name="objeto">Objeto del que crear una vista dinámica</param>
/// <returns>Objeto dinámico con propiedades locales</returns>
public static dynamic CrearAccesoDinamico(osBase objeto)
{
return new PropiedadesLocalesDinamicas(objeto);
}
/// <summary>
/// Clase interna que implementa un acceso dinámico a propiedades
/// </summary>
private class PropiedadesLocalesDinamicas : DynamicObject
{
private readonly osBase _objeto;
private readonly List<string> _propiedadesLocales;
public PropiedadesLocalesDinamicas(osBase objeto)
{
_objeto = objeto;
_propiedadesLocales = ObtenerPropiedadesLocales(objeto);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var nombrePropiedad = binder.Name;
if (_propiedadesLocales.Contains(nombrePropiedad))
{
var propInfo = _objeto.GetType().GetProperty(nombrePropiedad);
if (propInfo != null && propInfo.CanRead)
{
result = propInfo.GetValue(_objeto);
return true;
}
}
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var nombrePropiedad = binder.Name;
if (_propiedadesLocales.Contains(nombrePropiedad))
{
var propInfo = _objeto.GetType().GetProperty(nombrePropiedad);
if (propInfo != null && propInfo.CanWrite)
{
try
{
var valorConvertido = Convert.ChangeType(value, propInfo.PropertyType);
propInfo.SetValue(_objeto, valorConvertido);
return true;
}
catch (Exception)
{
// Silenciar errores de conversión
}
}
}
return false;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _propiedadesLocales;
}
}
}
}