Im folgenden wird gezeigt, wie mit Hilfe des Interfaces IConfigurationSectionHandler benutzerdefinierte Bereiche aus der app.config ausgelesen werden.
Aufbau, Sinn und Zweck von Konfigurationsdateien ist in den Online und Printmedien schon ausreichend dokumentiert. Deshalb will ich gleich auf das Erweitern der app.config um eigene, benutzerdefinierte Bereiche eingehen. Die app.config wurde so gekürzt, dass nur noch die eigene Sektion vorhanden ist. Im Bereich werden die einzelnen Sektionen aufgelistet. In diesem Beispiel ist es nur eine Sektion mit dem frei wählbaren, aber eindeutigen Namen mySection. Im Attribute type ist der Verweis auf eine Klasse, die das Interface IConfigurationSectionHandler implementieren muß. Dazu später mehr. Die Elemente der eigenen Sektion beginnen ab Zeile 6. Die darauf folgende XML-Struktur wurde von mir frei und willkürlich gewählt. Es ist eine Auflistung von drei Objekten.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="mySection" type="MySectionHandler.MyConfigurationSectionHandler, MyConfigurationSectionHandler"/> </configSections> <mySection> <values> <value valueAttribute="valAtt01"> <identifier>1</identifier> <settingValue> <newValue>11.1</newValue> <oldValue>1.1</oldValue> </settingValue> </value> <value valueAttribute="valAtt02"> <identifier>2</identifier> <settingValue> <newValue>22.2</newValue> <oldValue>2.2</oldValue> </settingValue> </value> <value valueAttribute="valAtt03"> <identifier>3</identifier> <settingValue> <newValue>33.3</newValue> <oldValue>3.3</oldValue> </settingValue> </value> </values> </mySection> </configuration>
Wie gelangt man jetzt an diese XML-Daten? Von zentraler Bedeutung ist die Klasse System.Configuration.ConfigurationManager. Über die statische Methode GetSection(string sectionName) werden die Daten der benannten Sektion angefordert. Allerdings bekommt man nicht direkt den XmlNode zurück. Sondern es wird die Klasse geladen, die im oberen Bereich unter
Das Ergebnis der Auswertung wird als typsichere Auflistung an den Aufrufer von Create() zurückgeliefert.
class MyConfigurationSectionHandler : IConfigurationSectionHandler { public object Create(object parent, object configContext, XmlNode section) { List<SectionValue> sectionValueList = new List<SectionValue>(); XmlNodeList nodeList = section.SelectNodes(@"//value"); foreach (XmlNode node in nodeList) { SectionValue sectionValue = new SectionValue(); sectionValue.Id = XmlConvert.ToInt32(node.SelectSingleNode(@"identifier").InnerText); sectionValue.Attribute = node.Attributes["valueAttribute"].Value; sectionValue.OldValue = XmlConvert.ToDouble(node.SelectSingleNode(@"settingValue/oldValue").InnerText); sectionValue.NewValue = XmlConvert.ToDouble(node.SelectSingleNode(@"settingValue/newValue").InnerText); sectionValueList.Add(sectionValue); } return sectionValueList; } }
Wurde einmal die ConfigurationSectionHandler-Klasse erstellt, ist es ein leichtes die gewünschten Informationen aus der Konfigurationsdatei auszulesen.
List<SectionValue> sectionValueList = ConfigurationManager.GetSection("mySection") as List<SectionValue>;
Es soll an dieser Stelle auch nicht verschwiegen werden, dass die Schnittstelle IConfigurationSectionHandler seit dem .NET Framework Version 2.0 als veraltet gilt. Statt dessen sollten von der Klasse ConfigurationSection abgeleitet werden. Hierzu werde ich noch ein Beispiel liefern. Auch muss beachtet werden, dass die Klasse, die das Interface IConfigurationSectionHandler implementiert, threadsicher und zustandsfrei ist. Create() muss also entsprechend erweitert werden, damit diese Methode von mehreren Threads aufgerufen werden kann.