Mover la configuración de app.config a db y usar el tipo de valor para establecer dinámicamente el tipo de datos de retorno

.net c# dapper

Pregunta

Tengo una aplicación de servicio de Windows que quiero administrar desde un sitio asp.net. A medida que mi aplicación ha crecido, mi lista de configuraciones en el archivo app.config también ha crecido. Por lo tanto, he decidido mover estas configuraciones a una tabla en mi SQLDB para poder rastrearlas y darme una forma de modificar las configuraciones desde el sitio de administración. Me encontré con un problema en el que intento almacenar el tipo de valor de configuración en la tabla y luego usarlo para cambiar la propiedad del valor al tipo almacenado. Por ejemplo, tengo bastantes TimeSpan definidos. En la tabla SQL, los datos se verían así.

guid    settingName     settingValue    settingType
936767f5-63b5-4844-9991-29f6f92c53f2    SMTimeStart    12:00:00    TimeSpan

Estoy tratando de usar el siguiente código para extraer la configuración y devolverla en el tipo correcto.

    public class SettingDataValue
    {
        public Guid guid { get; set; }
        public string SettingName { get; set; }
        public string SettingValue { get; set; }
        public string SettingType { get; set; }


    }
    public static dynamic getSettingFromDB(string name)
    {
        SettingDataValue s = new SettingDataValue();
        using (IDbConnection _db = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString), commandTimeout = null)
        {
            s = _db.Query<SettingDataValue>("Select Guid, SettingName, SettingValue ,SettingType from SiteSettings where settingName = '" + name + "'").SingleOrDefault();
        }
        PropertyInfo propertyInfo = s.GetType().GetProperty(s.SettingType);
        propertyInfo.SetValue(s, Convert.ChangeType(s.SettingValue, propertyInfo.PropertyType), null);

        return s.SettingValue;
    }

Sin embargo, cuando ejecuto esto obtengo una excepción de referencia nula en

propertyInfo.SetValue(s, Convert.ChangeType(s.SettingValue, propertyInfo.PropertyType), null);

Sé que la consulta funciona cuando la pruebo y la miro con el generador de perfiles sql. ¿Alguna idea o sugerencia?

Respuesta aceptada

Así que un par de cosas que tenía mal. Como David mencionó, no necesité usar la reflexión para obtener el tipo. En cambio, necesitaba usar el método Type.GetType para analizar el texto. Además, lo segundo es que los tipos de datos deben ser el espacio de nombres grabado con ellos.

Aquí está el código actualizado que está funcionando ahora.

    public class SettingDataValue
    {
        public Guid guid { get; set; }
        public string SettingName { get; set; }
        public string SettingValue { get; set; }
        public string SettingType { get; set; }

    }
    public static dynamic getSettingFromDB(string name)
    {

        SettingDataValue s = new SettingDataValue();
        using (IDbConnection _db = new SqlConnection(ConfigurationManager.ConnectionStrings["NetworkCafeConnectionString"].ConnectionString))
        {
            s = _db.Query<SettingDataValue>("Select guid, SettingName, SettingValue ,SettingType from SiteSettings where SettingName = '" + name + "'").FirstOrDefault();
        }
        Type type = Type.GetType(s.SettingType);
        var converter = TypeDescriptor.GetConverter(type);
        return converter.ConvertFrom(s.SettingValue);
    }

Aquí hay una muestra de los datos en la tabla sql.

guid        SettingName            SettingValue    SettingType
95473a84    SMCreateTime           00:12:00        System.TimeSpan
81037bdc    SMCreateEnabled        True            System.Boolean
99e06df7    SMUsername             Username        System.String

Respuesta popular

El problema que tiene no es que no esté recuperando datos, sino que PropertyInfo es nulo.

La línea:

PropertyInfo propertyInfo = s.GetType().GetProperty(s.SettingType);

Está tratando de encontrar la propiedad "TimeSpan" en el objeto SettingDataValue (usando la línea de datos que proporcionó). Como esta propiedad no existe, devuelve nulo. Luego, intenta establecer el valor de la propiedad y obtener la excepción de referencia nula.

Creo que lo que estás tratando de hacer es convertir el valor de la cadena al tipo de valor en el tipo de configuración. No necesitas usar el reflejo para eso. Recomiendo agregar una propiedad de solo lectura a su objeto SettingDataValue:

public object Value
{
    get
    {
        return SomeMethodThatConvertsYourStringValueToTarget();
    }
}

Luego, un método privado para realmente hacer la conversión.

private object SomeMethodThatConvertsYourStringValueToTarget();
{
    switch (SettingType)
    {
        case "TimeSpan":
            //conversion code
            break;
    }
}

A continuación, cambie su método getSettingsFromDb para devolver el objeto en lugar de dinámico. Entonces puedes usarlo como:

TimeSpan ts = (TimeSpan) getSettingsFromDb ("SMTimeStart");

De forma alternativa, puede crear un método para cada tipo de datos para que no tenga que presentar un caso al usarlo. Entonces podrías usarlo así:

TimeSpan ts = getTimeStampFromDb ("SMTimeStart");



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué