Unter .NET 2.0 ist es mit Ableitungen von [b]ConfigurationSection[/b] und [b]ConfigurationElement[/b] sehr einfach möglich die Konfigurations-Dateien um eigene Abschnitte zu erweiteren die dann Typsicher eingelesen und verwendet werden können. Möchte man nun die Attribute der Konfiguration direkt beim einlesen überprüfen und nicht erst wenn der Wert zur Laufzeit verwendet wird, so geht dies natürlich auch. So werden ein paar Standard-Validatoren mitgeliefert z.B. [b]IntegerValidator[/b] und [b]SubclassValidator[/b]. Einen eigenen Validator zu schreiben ist, wie so oft in .NET, natürlich auch möglich. Dazu sind nur zwei Schritte notwendig. [list] [*]Schreiben eines Validators auf Basis von [b]ConfigurationValidatorBase[/b][*]Schreiben eines Attributes auf Basis von [b]ConfigurationValidatorAttribute[/b][/list]Bei [b]ConfigurationValidatorBase[/b] müssen die Methoden [b]CanValidate()[/b] und [b]Validate()[/b] überschrieben werden. Hier an einem Beispiel eines Validators der überprüft ob eine in einer Eigenschaft angegebene Datei auch wirklich vorhanden ist. [c#] using System; using System.Configuration; using System.IO; namespace DerAlbert.Community.Configuration { public class FileExistsValidator : ConfigurationValidatorBase { public override void Validate(object value) { if (string.IsNullOrEmpty((string)value)) return; string path = GetPath((string) value); if (!File.Exists(path)) throw new ConfigurationErrorsException( string.Format("The file '{0}' does not exists", path)); } private string GetPath(string valuePath) { if (valuePath.StartsWith("~/") || valuePath.StartsWith("~\\\")) { return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, valuePath.Substring(2)); } else return valuePath; } public override bool CanValidate(Type type) { return (type == typeof(string)); } } } [/c#] Nun hat man zwar einen schönen Validator, jedoch muss dieser noch an die entsprechende Eigenschaft gebunden werden. Dies geschieht über ein Attribute auf Basis von [b]ConfigurationValidatorAttribute[/b]. Hier muss im einfachsten Fall nur die Eigenschaft [b]ValidatorInstance[/b] überschrieben werden um eine neue Instanz des eigenen Validators zu übergeben. [c#] using System.Configuration; namespace DerAlbert.Community.Configuration { public class FileExistsValidatorAttribute : ConfigurationValidatorAttribute { public override ConfigurationValidatorBase ValidatorInstance { get { return new FileExistsValidator(); } } } } [/c#] Sind zusätzliche Parameter für den Validator erforderlich um eine Gültigkeit zu ermitteln, so sind diese über den Konstrukturen des Attributes anzunehmen. Diese können dann direkt bei der Angabe des Attributes bei der Eigenschaft erfasst werden. Diese Parameter müssen wiederum an die Validator weitergeleitet werden z.B. mit dessen Konstruktor. In der Anwendung bei einem [b]ConfigurationElement[/b] sieht dies dann so aus. Gebunden ist der Validator hier an die Template-Eigenschaft. Somit wird schon beim einlesen der Konfiguration geprüft ob die Datei vorhanden ist und nicht erst wenn diese in der Anwendung wirklich gebraucht wird. [c#] using System; using System.ComponentModel; using System.Configuration; using DerAlbert.Community.Objects; namespace DerAlbert.Community.Configuration { public class EntryObjectSettings : ConfigurationElement { [ConfigurationProperty("name", IsRequired = true)] public string Name { get { return (string)base["name"]; } set { base["name"] = value; } } [ConfigurationProperty("type", IsRequired = true)] [TypeConverter(typeof(TypeTypeConverter))] [SubclassTypeValidator(typeof(BaseEntry))] public Type Type { get { return (Type)base["type"]; } set { base["type"] = value; } } [ConfigurationProperty("template", IsRequired = false)] [FileExistsValidator] public string Template { get { return (string)base["template"]; } set { base["template"] = value; } } } } [/c#] Der Vollständigkeithalber hier der entsprechende Abschnitt in der Konfigurationsdatei [xml] [/xml]