Se stai cercando una sezione di configurazione personalizzata come la seguente
<CustomApplicationConfig>
<Credentials Username="itsme" Password="mypassword"/>
<PrimaryAgent Address="10.5.64.26" Port="3560"/>
<SecondaryAgent Address="10.5.64.7" Port="3570"/>
<Site Id="123" />
<Lanes>
<Lane Id="1" PointId="north" Direction="Entry"/>
<Lane Id="2" PointId="south" Direction="Exit"/>
</Lanes>
</CustomApplicationConfig>
quindi è possibile utilizzare la mia implementazione della sezione di configurazione in modo da iniziare aggiungere il System.Configuration
riferimento dell'assembly al progetto
Guarda tutti gli elementi nidificati che ho usato, il primo è Credenziali con due attributi, quindi aggiungiamolo prima
Elemento credenziali
public class CredentialsConfigElement : System.Configuration.ConfigurationElement
{
[ConfigurationProperty("Username")]
public string Username
{
get
{
return base["Username"] as string;
}
}
[ConfigurationProperty("Password")]
public string Password
{
get
{
return base["Password"] as string;
}
}
}
PrimaryAgent e SecondaryAgent
Entrambi hanno gli stessi attributi e sembrano un indirizzo a un set di server per un primario e un failover, quindi devi solo creare una classe di elementi per entrambi come quelli seguenti
public class ServerInfoConfigElement : ConfigurationElement
{
[ConfigurationProperty("Address")]
public string Address
{
get
{
return base["Address"] as string;
}
}
[ConfigurationProperty("Port")]
public int? Port
{
get
{
return base["Port"] as int?;
}
}
}
Spiegherò come utilizzare due diversi elementi con una classe più avanti in questo post, saltiamo il SiteId in quanto non vi è alcuna differenza. Devi solo creare una classe come sopra con una sola proprietà. vediamo come implementare la raccolta Lanes
è diviso in due parti prima devi creare una classe di implementazione dell'elemento, quindi devi creare una classe di elementi della raccolta
LaneConfigElement
public class LaneConfigElement : ConfigurationElement
{
[ConfigurationProperty("Id")]
public string Id
{
get
{
return base["Id"] as string;
}
}
[ConfigurationProperty("PointId")]
public string PointId
{
get
{
return base["PointId"] as string;
}
}
[ConfigurationProperty("Direction")]
public Direction? Direction
{
get
{
return base["Direction"] as Direction?;
}
}
}
public enum Direction
{
Entry,
Exit
}
si può notare che un attributo di LanElement
è un'enumerazione e se si tenta di utilizzare qualsiasi altro valore nella configurazione che non è definito nell'applicazione di enumerazione, verrà lanciato System.Configuration.ConfigurationErrorsException
all'avvio. Ok consente di passare a Definizione raccolta
[ConfigurationCollection(typeof(LaneConfigElement), AddItemName = "Lane", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class LaneConfigCollection : ConfigurationElementCollection
{
public LaneConfigElement this[int index]
{
get { return (LaneConfigElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(LaneConfigElement serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new LaneConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((LaneConfigElement)element).Id;
}
public void Remove(LaneConfigElement serviceConfig)
{
BaseRemove(serviceConfig.Id);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(String name)
{
BaseRemove(name);
}
}
puoi notare che ho impostato il AddItemName = "Lane"
che puoi scegliere quello che ti piace per la voce della tua raccolta, preferisco usare "aggiungi" quello predefinito ma l'ho modificato solo per il bene di questo post.
Ora tutti i nostri elementi nidificati sono stati implementati ora dovremmo aggregare tutti quelli in una classe che deve implementare System.Configuration.ConfigurationSection
CustomApplicationConfigSection
public class CustomApplicationConfigSection : System.Configuration.ConfigurationSection
{
private static readonly ILog log = LogManager.GetLogger(typeof(CustomApplicationConfigSection));
public const string SECTION_NAME = "CustomApplicationConfig";
[ConfigurationProperty("Credentials")]
public CredentialsConfigElement Credentials
{
get
{
return base["Credentials"] as CredentialsConfigElement;
}
}
[ConfigurationProperty("PrimaryAgent")]
public ServerInfoConfigElement PrimaryAgent
{
get
{
return base["PrimaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("SecondaryAgent")]
public ServerInfoConfigElement SecondaryAgent
{
get
{
return base["SecondaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("Site")]
public SiteConfigElement Site
{
get
{
return base["Site"] as SiteConfigElement;
}
}
[ConfigurationProperty("Lanes")]
public LaneConfigCollection Lanes
{
get { return base["Lanes"] as LaneConfigCollection; }
}
}
Ora puoi vedere che abbiamo due proprietà con nome PrimaryAgent
ed SecondaryAgent
entrambi hanno lo stesso tipo ora puoi capire facilmente perché abbiamo avuto solo una classe di implementazione contro questi due elementi.
Prima di poter utilizzare questa sezione di configurazione appena inventata nel tuo app.config (o web.config) devi solo dire all'applicazione che hai inventato la tua sezione di configurazione e dargli un po 'di rispetto, per farlo devi aggiungere le seguenti righe in app.config (potrebbe essere subito dopo l'inizio del tag root).
<configSections>
<section name="CustomApplicationConfig" type="MyNameSpace.CustomApplicationConfigSection, MyAssemblyName" />
</configSections>
NOTA: MyAssemblyName dovrebbe essere senza .dll, ad esempio se il nome del file dell'assembly è myDll.dll, utilizzare myDll anziché myDll.dll
per recuperare questa configurazione utilizzare la seguente riga di codice in qualsiasi punto dell'applicazione
CustomApplicationConfigSection config = System.Configuration.ConfigurationManager.GetSection(CustomApplicationConfigSection.SECTION_NAME) as CustomApplicationConfigSection;
Spero che il post sopra ti possa aiutare a iniziare con un tipo un po 'complicato di sezioni di configurazione personalizzate.
Happy Coding :)
**** Modifica **** Per abilitare LINQ LaneConfigCollection
devi implementarloIEnumerable<LaneConfigElement>
E aggiungi la seguente implementazione di GetEnumerator
public new IEnumerator<LaneConfigElement> GetEnumerator()
{
int count = base.Count;
for (int i = 0; i < count; i++)
{
yield return base.BaseGet(i) as LaneConfigElement;
}
}
per le persone che sono ancora confuse su come funziona davvero la resa leggi questo bell'articolo
Due punti chiave presi dall'articolo precedente sono
in realtà non termina l'esecuzione del metodo. yield return mette in pausa l'esecuzione del metodo e alla successiva chiamata (per il successivo valore di enumerazione), il metodo continuerà a essere eseguito dall'ultima chiamata di return di rendimento. Sembra un po 'confuso, penso ... (Shay Friedman)
La resa non è una funzionalità del runtime .Net. È solo una funzione del linguaggio C # che viene compilata in un semplice codice IL dal compilatore C #. (Lars Corneliussen)