Im fünften Teil meiner Serie möchte ich auf erweiterte Möglichkeiten der Konfiguration des Dienstes eingehen. Über die ApplicationSettings ist es in Visual Studio ganz einfach möglich Strings, Integer usw. als globale Anwendungseinstellungen (web.config bei ASP.NET – sonst app.config) abzuspeichern:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="userSettings" type="..."> <section name="DBCopyService.Properties.Settings" type="..." allowExeDefinition="MachineToLocalUser" requirePermission="false" /> </sectionGroup> </configSections> <userSettings> <DBCopyService.Properties.Settings> <setting name="ServerName" serializeAs="String"> <value>serverName</value> </setting> </DBCopyService.Properties.Settings> </userSettings> </configuration>
Der Zugriff auf die Einstellung “ServerName” erfolgt dann ganz einfach über Properties.Settings.Default.ServerName. Man kann sogar zur Laufzeit die Settings ändern und wieder abspeichern.
Wenn man jedoch komplexere Strukturen in den Einstellungen ablegen möchte, kommt man um etwas Code nicht mehr herum. Im folgenden Beispiel lege ich die neue Sektion “entrances” an, um dort dann beliebig viele Eingangsverzeichnisse überwachen zu lassen:
Eintrag in der app.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="DBCopyService"> <section name="entrances" type="DBCopyService.EntranceSection,DBCopyService" /> </sectionGroup> </configSections> <DBCopyService> <entrances> <entrance name="entrance1" path="C:\Eingang\" mailAddress="mail@server.de" /> <entrance name="entrance2" path="C:\Eingang2\" mailAddress="mail2@server.de" /> </entrances> </DBCopyService> </configuration>
Zugriff über Ableitung von ConfigurationElement, ConfigurationElementCollection und ConfigurationSection:
using System; using System.Collections.Generic; using System.Text; using System.Configuration; namespace DBCopyService { public sealed class EntranceElement : ConfigurationElement { /// <summary> /// Gets or sets the name. /// </summary> /// <value>The name.</value> [ConfigurationProperty("name", IsKey = true, IsRequired = true)] public string Name { get { return (string)base["name"]; } set { base["name"] = value; } } /// <summary> /// Gets or sets the mail address. /// </summary> /// <value>The mail address.</value> [ConfigurationProperty("mailAddress", IsRequired = true)] public string MailAddress { get { return (string)base["mailAddress"]; } set { base["mailAddress"] = value; } } /// <summary> /// Gets or sets the path. /// </summary> /// <value>The path.</value> [ConfigurationProperty("path", IsRequired = true)] public string Path { get { return (string)base["path"]; } set { base["path"] = value; } } } }
using System; using System.Collections.Generic; using System.Text; using System.Configuration; namespace DBCopyService { public sealed class EntranceCollection : ConfigurationElementCollection { protected override ConfigurationElement CreateNewElement() { return new EntranceElement(); } protected override object GetElementKey( ConfigurationElement element) { return ((EntranceElement)element).Name; } public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } protected override string ElementName { get{ return "entrance"; } } } }
using System; using System.Collections.Generic; using System.Text; using System.Configuration; namespace DBCopyService { public sealed class EntranceSection : ConfigurationSection { [ConfigurationProperty("", IsDefaultCollection = true)] public EntranceCollection Entrances { get { return (EntranceCollection)base[""]; } } } }
Mit Hilfe dieser Klassenstruktur (Element, Collection, Section) kann man nun bequem auf die Section zugreifen:
EntranceSection entranceSection = ConfigurationManager.GetSection("DBCopyService/entrances") as EntranceSection; foreach (EntranceElement element in entranceSection.Entrances) Console.WriteLine( string.Format("Path {0}, Mail {1}", element.Path, element.MailAddress));