2010-11-03 12 views
7

Tengo este extraño problema ... en mi código si establezco el valor de IsRequired en falso o verdadero, entonces se mantiene falso. Sin embargo, si pongo un DefaultValue, ¿funciona?C# - ConfigurationSection isRequired attribute

El código no es de trabajo:

public class FtpSettingsSection : ConfigurationSection 
{ 
    [ConfigurationProperty("host", IsRequired = true)] 
    public HostElement Host 
    { 
     get { return (HostElement)this["host"]; } 
     set { this["host"] = value; } 
    } 

} 

public class HostElement : ConfigurationElement 
{ 
    [ConfigurationProperty("URL", IsRequired = true)] 
    public string URL 
    { 
     get { return (string)this["URL"]; } 
     set { this["URL"] = value; } 
    } 
} 

y el código de trabajo es:

public class FtpSettingsSection : ConfigurationSection 
{ 
    [ConfigurationProperty("host", DefaultValue = "", IsRequired = true)] 
    public HostElement Host 
    { 
     get { return (HostElement)this["host"]; } 
     set { this["host"] = value; } 
    } 

} 

public class HostElement : ConfigurationElement 
{ 
    [ConfigurationProperty("URL", DefaultValue = "", IsRequired = true)] 
    public string URL 
    { 
     get { return (string)this["URL"]; } 
     set { this["URL"] = value; } 
    } 
} 

¿Cómo es que necesito fijar ValorPredeterminado a ""?

Respuesta

0

Supongo que no tiene el valor de la propiedad URL serializado en su configuración. Por lo tanto, cuando se carga la configuración, ConfigurationManager verifica los atributos para ver si el valor de la propiedad es necesario y luego lanza una excepción si no encuentra ningún valor. Si se establece el valor predeterminado, ese valor se usa si no se encuentra ninguno en la configuración.

+1

El primer ejemplo de código dosent arroja alguna excepción, incluso si la propiedad del host no está definida en el archivo de configuración? – ebb

+0

El primer ejemplo lanzará una excepción, el segundo con el atributo predeterminado no lo hará. – dexter

+0

En realidad, probé esto y el PRIMER ejemplo no lanza una excepción. En una aplicación de consola de prueba, IsRequired parece estar siendo ignorado. Si se requiere, no debe poner el valor predeterminado porque entonces en realidad no es necesario. Si lo marca IsRequired = true, debe arrojar una excepción si no proporciona un valor predeterminado, pero no lo hace. Probé en .Net 4. –

6

He encontrado el mismo problema y he encontrado la solución aquí http://msdn.microsoft.com/en-us/library/system.configuration.configurationpropertyattribute%28v=vs.90%29.aspx#1. El comentario sobre ConfigurationPropertyAttribute no es completamente correcto, pero explica los conceptos básicos del problema:

la IsRequired miembro del ConfigurationPropertyAttribute no funciona cuando se aplica a un objeto secundario (que deriva de ConfigurationElement). Cuando el subsistema refleja los atributos de la sección/elemento principal para determinar qué propiedades de configuración se definen, creará una nueva instancia (del tipo apropiado) para cada elemento secundario y la almacenará en la lista de valores del padre. Más tarde, cuando valida si se han especificado o no todas las propiedades requeridas, no se puede diferenciar entre un elemento hijo inicializado predeterminado y uno que estaba explícitamente contenido en el archivo de configuración.

La solución más ideal sería declarar mediante programación los elementos necesarios a través de la clase ConfigurationProperty. Esto requiere mucho más trabajo que el enfoque declarativo. Una alternativa ...

Por lo que yo sé, la alternativa es incorrecta.

Un ejemplo del modelo programático se puede encontrar en la página ConfigurationProperty. Me las arreglé para solucionar el problema al declarar las propiedades que necesito en el constructor de mi elemento personalizado y dejar todo lo demás igual.

Sospecho que no funciona realmente cuando agrega DefaultValue, sino que lanza una excepción por un motivo diferente. Tendrá que desglosar hasta el final de la cadena InnerException para encontrar el ConfigurationErrorsException. El mensaje correcto cuando falta una propiedad requerida es "No se encontró el atributo 'host' requerido. (C: \ path \ to \ yourproject \ bin \ Debug \ yourproject.vshost.exe.Config line ##)"

Cuando proporciona un valor predeterminado de cadena vacía, el subsistema de configuración intentará analizar esa cadena en un HostElement y fallará. El ConfigurationErrorsException resultante tiene el mensaje "El valor predeterminado de la propiedad 'host' no se puede analizar El error es: Referencia de objeto no establecida en una instancia de un objeto. (C: \ path \ to \ yourproject \ bin \ Debug \ yourproject.vshost.exe.Config line ##) "

3

Lo siento por necroposting, pero este problema también me afecta pero de una manera más peculiar y mi solución también se aplica a la pregunta formulada.

Implementé recargar una configuración sin reiniciar un proceso. Cuando se inicia el proceso, el atributo IsRequired se "ignora" y el ConfigurationElement se inicializa silenciosamente con los valores predeterminados. ¡Pero cuando se vuelve a cargar la configuración, se respeta el IsRequired atribuido! ¡Así que codifiqué la configuración de recarga en el inicio del proceso y resolvió el problema de la excepción perdida!

Pseudocódigo:

config = (SampleConfiguration)ConfigurationManager.GetSection(ConfigSectionName); 
// <-- no exception thrown for missing required properties 

ConfigurationManager.RefreshSection(ConfigSectionName); 

config = (SampleConfiguration)ConfigurationManager.GetSection(ConfigSectionName); 
// <-- exception thrown! 
2

Desenterrar un hilo muerto. Pero accidentalmente encontré una solución para esto.

En su constructor de sección personalizada, haga referencia a ElementInformation de un elemento personalizado. Al hacer eso, se creará otra instancia de su sección personalizada en el contexto del elemento. Y por alguna razón que no entiendo completamente, se respeta la propiedad IsRequired.

public class FtpSettingsSection : ConfigurationSection 
{ 
    public FtpSettingsSection() 
    { 
     // force it to double load. 
     if (this.Host.ElementInformation.IsPresent) ; 
    } 

    [ConfigurationProperty("host", IsRequired = true)] 
    public HostElement Host 
    { 
     get { return (HostElement)this["host"]; } 
     set { this["host"] = value; } 
    } 
} 
Cuestiones relacionadas