2010-11-03 4 views
7

Sto riscontrando questo strano problema ... nel mio codice se imposto il valore di IsRequired su false o true allora rimane falso .. Tuttavia se inserisco un valore predefinito funziona?C# - ConfigurationSection isRequired Attributo

Il codice non-lavoro è:

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; } 
    } 
} 

e il codice di lavoro è:

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; } 
    } 
} 

Come mai che ho bisogno di impostare DefaultValue ""?

risposta

0

Suppongo che tu non abbia il valore di proprietà dell'URL serializzato nella configurazione. Pertanto, quando viene caricata la configurazione, ConfigurationManager controlla gli attributi per vedere se è richiesto il valore della proprietà e quindi genera un'eccezione se non trova alcun valore. Se il valore predefinito è impostato, tale valore viene utilizzato se non è stato trovato alcun valore nella configurazione.

+1

Il primo esempio di codice dosent genera eccezioni anche se la proprietà host non è definita nel file di configurazione? – ebb

+0

Il primo esempio genererà un'eccezione, la seconda con l'attributo predefinito no. – dexter

+0

In realtà ho provato questo e il primo esempio non genera un'eccezione. In un'app console di prova IsRequired sembra essere ignorata. Se è richiesto non è necessario inserire il valore predefinito perché in realtà non è richiesto. Se lo contrassegni, IsRequired = true, allora dovrebbe generare un'eccezione se non fornisci un valore predefinito, ma non lo fa. Ho provato in .Net 4. –

6

Ho riscontrato lo stesso problema e ho trovato la soluzione qui http://msdn.microsoft.com/en-us/library/system.configuration.configurationpropertyattribute%28v=vs.90%29.aspx#1. Il commento sulla ConfigurationPropertyAttribute non è del tutto corretto, ma spiega le basi del problema:

La IsRequired membro del ConfigurationPropertyAttribute non funziona se applicato a un oggetto figlio (derivante da ConfigurationElement). Quando il sottosistema riflette gli attributi della sezione/elemento padre per determinare quali proprietà di configurazione sono definite, creerà una nuova istanza (del tipo appropriato) per ogni elemento figlio e la memorizzerà nell'elenco dei valori del genitore. Successivamente, quando convalida se tutte le proprietà richieste sono state specificate o meno, non può distinguere tra un elemento figlio inizializzato predefinito e uno che era esplicitamente contenuto nel file di configurazione.

La soluzione più ideale sarebbe quella di dichiarare programmaticamente gli elementi richiesti tramite la classe ConfigurationProperty. Ciò richiede un lavoro più consistente rispetto all'approccio dichiarativo. Un'alternativa ...

Per quanto posso dire l'alternativa è errata.

Un esempio del modello programmatico è disponibile nella pagina ConfigurationProperty. Sono riuscito a risolvere il problema per me stesso dichiarando le proprietà che ho bisogno richiesto nel costruttore del mio elemento personalizzato e lasciando tutto il resto lo stesso.

Ho il sospetto che per te non funzioni effettivamente quando aggiungi DefaultValue, ma piuttosto un'eccezione per un motivo diverso. Dovrai eseguire il drill down fino alla fine della catena InnerException per trovare lo ConfigurationErrorsException. Il messaggio corretto quando una proprietà necessaria che manca è " 'host' attributo richiesto non trovato. (C: \ percorso \ a \ ProgettoUtente \ line bin \ Debug \ yourproject.vshost.exe.Config ##)"

Quando si fornisce un valore predefinito di stringa vuota, il sottosistema di configurazione proverà ad analizzare tale stringa in un HostElement e avrà esito negativo. Il risultato ConfigurationErrorsException ha il messaggio "Impossibile analizzare il valore predefinito della proprietà 'host' L'errore è: Riferimento oggetto non impostato su un'istanza di un oggetto. (C: \ percorso \ al \ ilproject \ bin \ Debug \ linea di comando yourproject.vshost.exe.Config ##) "

3

Ci scusiamo per la necropostazione, ma questo problema mi ha colpito anche se in un modo più particolare e la mia soluzione si applica anche alla domanda posta.

Ho implementato il ricaricamento di una configurazione senza riavviare un processo. All'avvio del processo, l'attributo IsRequired è "ignorato" e lo ConfigurationElement viene inizializzato automaticamente con i valori predefiniti. Ma quando la configurazione viene ricaricata, viene rispettato l'attributo IsRequired! Così ho ricollegato hardcoded la configurazione all'avvio del processo e ha risolto il problema dell'eccezione mancante!

Pseudocode:

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

ConfigurationManager.RefreshSection(ConfigSectionName); 

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

Scavare un filo morto. Ma per caso ho trovato un problema.

Nel costruttore della sezione personalizzata, creare un riferimento a ElementInformation di un elemento personalizzato. Facendo ciò, verrà creata un'altra istanza della sezione personalizzata nel contesto dell'elemento. E per qualche ragione che non capisco completamente, la proprietà IsRequired è onorata.

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; } 
    } 
}