Tipos inmutables como propiedades de configuración
-
22-07-2019 - |
Pregunta
¿Es posible usar tipos inmutables como propiedades de configuración con la API de configuración de .NET?
Digamos que tengo un tipo inmutable llamado MyClass:
public class ImmutableClass
{
private readonly int value;
public ImmutableClass(int value)
{
this.value = value;
}
public int Value
{
get { return this.value; }
}
}
Me gustaría usar este tipo como una propiedad de configuración en una Sección de configuración:
public class MyConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("foo")]
public ImmutableClass Foo
{
get { return (ImmutableClass)base["foo"]; }
set { base["foo"] = value; }
}
}
Cuando hago esto, no puedo serializar y deserializar MyConfigurationSection porque arroja esta excepción:
System.Configuration.ConfigurationErrorsException: el valor de la propiedad 'criterio' no se puede convertir en cadena. El error es: No se puede encontrar un convertidor que admita la conversión a / desde una cadena para la propiedad 'criterio' del tipo 'FindCriterion'.
Si obtengo ImmutableClass de ConfigurationElement, obtengo esta excepción cuando intento serializar y deserializar la sección de configuración:
System.Reflection.TargetInvocationException: el destino de una invocación ha lanzado una excepción. --- > System.Reflection.TargetInvocationException: el destino de una invocación ha lanzado una excepción. --- > System.MissingMethodException: no hay un constructor sin parámetros definido para este objeto.
Tengo control total sobre ImmutableClass, por lo que puedo implementar la interfaz que sea necesaria.
¿Hay alguna forma de conectarme a la API de configuración para que ImmutableClass pueda usarse de esta manera?
Solución
Es posible que pueda usar algunos TypeConverters para ayudar al proceso (enlace a System.Configurations.ConfigurationConverter).
La verdadera pregunta es ¿por qué quieres causarte tantos problemas? Solo hay algunas veces en que es mejor recostarse y tomarlo que pelear. Algunas partes del marco son frustrantes si intenta hacerlo de otra manera que no sea la específica establecida para usted ...
Otros consejos
Personalmente, creo que sería mejor separar los datos en la sección de configuración (que aparentemente debe ser mutable) y cómo los representa en su modelo de objetos. No hay nada que le impida tener dos representaciones: una versión simple (DTO / POCO) para la configuración y su versión personalizada (inmutable en este caso) para uso real en su aplicación.
Abandonaría esa maldición porque la idea está maldita al fracaso. Todos los manejadores de la sección de configuración deben tener un constructor predeterminado (sin parámetros). Este no es el caso con su objeto inmutable.
La solución más simple es poner otro nivel de abstracción entre la configuración y su aplicación. Puede aplicar el patrón de proveedor de configuración y eso convertiría el "gratis para todos" clases mutables de la sección de configuración en clases inmutables que luego serían consumidas por su aplicación.
Debo decir que así es como deben usarse las secciones de configuración. Sé que hay una opción de retroceso, pero nunca la he usado antes.
El código podría tener un aspecto similar al siguiente:
El controlador de configuración
public class SectionHandler : ConfigurationSection
{
[ConfigurationProperty("foo")]
public MyObject ConfigurationValue
{
get { return (MyObject) this["foo"]; }
}
}
Después de obtener el valor de configuración del archivo XML y ponerlo en un objeto, use el patrón del proveedor de configuración para consumir la configuración en su aplicación.
El proveedor de configuración podría verse así:
public MyConfigurationProvider : IMyconfigurationProvider
{
public MyImmutabble ConfigurationValue
{
get
{
var configurationvalue = (MyObject) ConfigurationManager.GetSection("mySection");
return new MyImmutable(configurationvalue.ConfigurationValue);
}
}
}
Así es como lo hago y hasta ahora me ha servido.
Espero que ayude.