Name des Programms:
ApplicationSettings.dll v1.2
Beschreibung:
Diese Dll nimmt sehr viel Arbeit beim Verwalten von Anwendungseinstellungen ab. Bei der ersten Verwendung wird ein XML-Schema verwendet, um eine Dll zu generieren, die die gewünste Struktur beinhaltet. Das XML-Schema kann in Visual Basic IDEs praktischerweise über den integrierten XML-Parser angegeben werden (Codebeispiele siehe weiter unten).
Die Einstellungen werden im XML-Format abgespeichert.
Dabei ist es möglich, durch das ableiten eigener TypeConverter, selbst das Format von gespeicherten Daten zu bestimmen (es sollte sogar möglich sein, komplette XML-Elemente als Daten abzuspeichern, aber dafür übernehme ich keine Garantie ).
Optional können die Einstellungs-Container das INotifyPropertyChanged-Interface implementieren, wodurch DataBinding möglich ist.
Es kann auch angegeben werden, das für jede Enstellung ein entsprechendes (separates) Event erstellt wird, das ausgelöst wird, wenn sich die Einstellung ändert.
Klassendiagramme:
Ich habe mir erlaubt, die Liste etwas zu kürzen, denn viele Klassen werden nur von den generierten Assemblies verwendet.
Friend und Private Member sind ebenfalls nicht aufgelistet.
Spoiler anzeigen
Verwendete Programmiersprache und IDE:
Visual Basic .Net (IDE: Microsoft VisualStudio 2010 Express)
Systemanforderungen:
.Net Framework 4.0
Tutorial für Verwendung:
Spoiler anzeigen
XML-Schema:
Anhand eines Beispiels erklärt:
Das äußerste Element gibt den Haupt-Namespace der Assembly an. In diesem Fall "Testanwendung".
In diesem NameSpace wird eine Klasse namens "Settings" generiert. Diese Klasse hat statische Properties mit den Namen der Unterelemente, also in diesem Fall "MainWindow", "DebugWindow" und "IO". Die Typen dieser Properties (Klassen) werden im Namespace "Testanwendung.Generated" angelegt. Die IO-Property ist eine Ausnahme. Sie befindet sich im NameSpace "Testanwendung.Reserved". Warum das so ist, erkläre ich weiter unten.
Diese Klassen haben dann ihre weiteren Properties. Diese sind dann nicht mehr statisch.
Diese Properties können eine dieser beiden Möglichkeiten sein, nicht aber beides gleichzeitig:
Das IO-Element kann drei veschiedene Unterelemente beinhalten: File, Directory und SpecialDirectory. Das sind die Eigenschaften dieser Elemente:
Anwendung:
Im entsprechenden Projekt muss ein Verweis auf die ApplicationSettings.dll hinzugefügt werden. Dann wird in einer Methode, die Funktion
Der Code muss einmal ausgeführt werden, dann kann er auskommentiert werden.
Die generierte Dll kann jetzt optional in den gewünschten Ordner verschoben werden, wenn dieser nicht dem angegebenen Pfad entspricht, aber ich empfehle, den Pfad von vornherein richtig zu wählen, weil dann nicht bei jeder Änderung die Dll neu kopiert werden muss.
Anschließend wird ein Verweis auf diese generierte Dll hinzugefügt. Jetzt kann die Dll verwendet werden.
Jetzt ist es vom Vorteil, wenn das äußerste Element den selben Namen hat, wie der Standard-NameSpace des Projektes. Denn dadurch ist die Settings-Klasse direkt aufrufbar und man spart sich die Angabe bzw. den Import des NameSpaces.
Jetzt müssen beim Starten der Anwendung (zum Beispiel im Konstruktor der Startform) die Einstellungen geladen werden. Das geschieht in zwei Schritten:
Zuerst muss die IO-Klasse initialisiert werden, damit sie die Pfade korrekt zusammenstellen kann. Dazu muss ihr der Dateipfad zur ausgeführten Datei übergeben werden. Das ist üblicherweise
Im zweiten Schritt werden die Einstellungen aus der XML-Datei gelesen. Dazu wird der Pfad zur XML-Datei benötigt. Es bietet sich an, in der IO-Klasse eine Property für diesen Pfad anzulegen (beispielsweise den Programmordner oder unter AppData\Local einen Unterordner). Natürlich funktionieren auch alle anderen Pfade. Möglicherweise funktionieren beim Laden auch URLs.
Man beachte, dass die Properties in der IO-Klasse keine Strings sondern eigene Klassen sind, die das Arbeiten damit erleichtern. Deshalb muss vom Objekt, das von der SettingsXmlFile-Property zurückgegeben wird, die Path-Property abgerufen werden.
Beim Beenden der Anwendung (z.B. OnClosing) müssen die Einstellungen wieder gespeichert werden.
Dazu muss ebenfalls der Pfad zur XML-Datei angegeben werden:
Nun können die Einstellungen verwendet werden. Beispiele:
Download:
ApplicationSettings v1.2.zip (23KB gepackt, 56.5KB entpackt)
ApplicationSettings.xml (12.3KB) (XML-Doku für Wiederverwendung)
Lizenz/Weitergabe:
Darf beliebig weitergegeben werden, solange dafür kein Geld verlangt wird.
Einkompilieren erlaubt (Erwähnung wäre nett).
Dekompilieren erlaubt, ich beantworte Fragen zum Code aber auch gerne selbst.
ApplicationSettings.dll v1.2
Beschreibung:
Diese Dll nimmt sehr viel Arbeit beim Verwalten von Anwendungseinstellungen ab. Bei der ersten Verwendung wird ein XML-Schema verwendet, um eine Dll zu generieren, die die gewünste Struktur beinhaltet. Das XML-Schema kann in Visual Basic IDEs praktischerweise über den integrierten XML-Parser angegeben werden (Codebeispiele siehe weiter unten).
Die Einstellungen werden im XML-Format abgespeichert.
Dabei ist es möglich, durch das ableiten eigener TypeConverter, selbst das Format von gespeicherten Daten zu bestimmen (es sollte sogar möglich sein, komplette XML-Elemente als Daten abzuspeichern, aber dafür übernehme ich keine Garantie ).
Optional können die Einstellungs-Container das INotifyPropertyChanged-Interface implementieren, wodurch DataBinding möglich ist.
Es kann auch angegeben werden, das für jede Enstellung ein entsprechendes (separates) Event erstellt wird, das ausgelöst wird, wenn sich die Einstellung ändert.
Klassendiagramme:
Ich habe mir erlaubt, die Liste etwas zu kürzen, denn viele Klassen werden nur von den generierten Assemblies verwendet.
Friend und Private Member sind ebenfalls nicht aufgelistet.
VB.NET-Quellcode
- Namespace ApplicationSettings
- Class DirectoryFromEnvironmentDirectory : Inherits DirectoryIdentifierBase
- ReadOnly Property SpecialDirectory As Environment.SpecialFolder
- Sub New(NewSpecialDirectory As Environment.SpecialFolder)
- Class DirectoryFromPath : Inherits DirectoryIdentifierBase
- Sub New(NewPath As String)
- MustInherit Class DirectoryIdentifierBase : Inherits IdentifierBase
- Function GetSubDirectory(DirectoryName As String) As DirectoryIdentifierBase
- Function GetFileInDirectory(FileName As String) As FileIdentifierBase
- Class FileFromPath : Inherits FileIdentifierBase
- Sub New(NewPath As String)
- MustInherit Class FileIdentifierBase : Inherits IdentifierBase
- MustOverride ReadOnly Property ContainingDirectory As DirectoryIdentifierBase
- MustOverride ReadOnly Property FileName As String
- Class FileInDirectory : Inherits FileIdentifierBase
- Sub New(NewContainingDirectory As DirectoryIdentifierBase, NewFileName As String)
- Class Generator
- Shared Sub CreateSettingsAssembly(Path As String, AssemblyDescription As System.Xml.Linq.XElement)
- Class GeneratorException : Inherits Exception
- Sub New(Message As String)
- MustInherit Class IdentifierBase
- MustOverride ReadOnly Property Path As String
- Class NopeException : Inherits Exception
- Sub New()
- Sub New(NewMessage As String)
- Class XMLParseException : Inherits Exception
- Sub New(NewElement As XElement, NewMessage As String)
Verwendete Programmiersprache und IDE:
Visual Basic .Net (IDE: Microsoft VisualStudio 2010 Express)
Systemanforderungen:
.Net Framework 4.0
Tutorial für Verwendung:
XML-Schema:
Anhand eines Beispiels erklärt:
XML-Quellcode
- <Testanwendung>
- <MainWindow>
- <WindowTitle TypeCode="String"/>
- <BackGroundColor TypeName="System.Drawing.Color"/>
- <CodeWindow>
- <SyntaxHighlighting TypeCode="String"/>
- </CodeWindow>
- </MainWindow>
- <DebugWindow>
- <InUse TypeCode="Boolean"/>
- </DebugWindow>
- <IO>
- <Directory Parent="ApplicationDirectory" Name="SettingsDirectory" Path="Settings">
- <File Name="SettingsXmlFile" Path="ApplicationSettings.xml"/>
- </Directory>
- <Directory Name="Desktop">C:\Users\Niko\Desktop</Directory>
- <File Parent="Desktop" Name="TestTextFile">Test.txt</File>
- <SpecialDirectory Name="AppData" Path="LocalApplicationData">
- <Directory Name="AppDataSettingsDirectory" Path="Testanwendung">
- <File Name="AppDataSettingsXmlFile">ApplicationSettings.xml</File>
- </Directory>
- </SpecialDirectory>
- </IO>
- </Testanwendung>
Das äußerste Element gibt den Haupt-Namespace der Assembly an. In diesem Fall "Testanwendung".
In diesem NameSpace wird eine Klasse namens "Settings" generiert. Diese Klasse hat statische Properties mit den Namen der Unterelemente, also in diesem Fall "MainWindow", "DebugWindow" und "IO". Die Typen dieser Properties (Klassen) werden im Namespace "Testanwendung.Generated" angelegt. Die IO-Property ist eine Ausnahme. Sie befindet sich im NameSpace "Testanwendung.Reserved". Warum das so ist, erkläre ich weiter unten.
Diese Klassen haben dann ihre weiteren Properties. Diese sind dann nicht mehr statisch.
Diese Properties können eine dieser beiden Möglichkeiten sein, nicht aber beides gleichzeitig:
- Elemente mit nur Unterelementen (
<CodeWindow>...</CodeWindow>
):
Diese Properties enthalten ihrerseits wieder Properties. Die Namen der XML-Elemente stellen die Namen der Properties dar. Die Klassen werden ebenfalls im Generated-NameSpace angelegt. - Elemente mit nur Attributen (
<SyntaxHighlighting TypeCode="String"/>
):
Diese Properties werden zum Speichern und Auslesen von Werten verwendet. Die Namen der XML-Elemente stellen die Namen der Properties dar. Der Typ wird anhand einer dieser beiden Attribute festgestellt (beide gleichzeitig zu verwenden ist nicht möglich):
- TypeCode:
Ein Wert aus dem Enum System.TypeCode. Nicht erlaubt sind Empty und DBNull. Die Typen werden entsprechend dem TypeCode ausgewählt. "String" ergibt den Typ System.String. Es gibt folgende Aliase: "Int", "Integer" -> "Int32" und "Bool" -> "Boolean" - TypeName:
Ein voll qualifizierter Name eines Typs. Wichtig ist hierbei, dass es zur Laufzeit einen TypeConverter für diesen Typ gibt, der von und zu String konvertieren kann.
Beispielsweise System.Drawing.Color verwendet System.Drawing.ColorConverter. Ein TypeConverter wird üblicherweise so mit dem Typ verknüpft:
Wird der Typ garnicht gefunden kann es daran liegen, dass der Name nicht richtig angegeben wurde. Typen, die sich nicht in der mscorlib.dll befinden, müssen mit Namespace qualifiziert sein. Oder die benötigte Assembly ist einfach nicht geladen.
Wird der Typ mehrmals gefunden, kann es daran liegen, dass er in mehreren Assemblies gleich definiert ist. Abgesehen davon, dass das nicht vorkommen sollte, könnte man versuchen, den AssemblyQualifiedName anzugeben. Diesen erhält man von einem beliebigen Typen, indem manGetType(TypName).AssemblyQualifiedName
ausliest. Das könnte helfen, den benötigten Namen zu finden. Weiter sollte man alle Assemblies, die die Namenskollisionen auslösen, entfernen, sofern das möglich ist. - DefaultValue:
Die String-Darstellung des Standardwertes dieser Einstellung. Die Einstellung hat standardmäßig diesen Wert, bis er durch eine Zuweisung oder durch das Laden aus einer XML-Datei verändert wird.
Auch hier ist wichtig, dass ein passender TypeConverter vorhanden ist.
- TypeCode:
Das IO-Element kann drei veschiedene Unterelemente beinhalten: File, Directory und SpecialDirectory. Das sind die Eigenschaften dieser Elemente:
- Name:
Dieses Attribut gibt den Namen der Property an, die in der IO-Klasse generiert wird. Sollte so aussagekräftig wie möglich sein. "ApplicationDirectory" und "ApplicationExecutableFile" sind als Namen ungültig, da diese Properties bereits in der Basisklasse vordefiniert sind. Weiters dürfen Namen nicht doppelt vorkommen, da es in der IO-Klasse keine Gruppierung gibt. - Parent:
Ein übergeordnetes Element kann durch die Verschachtelung im XML-Schema oder durch ein Attribut namens "Parent" festgelegt sein. Im Beispiel oben ist das File-Element "SettingsXmlFile" dem Directory-Element "SettingsDirectory" untergeordnet. Ebenfalls ist das File-Element "TestTextFile" dem Directory-Element "AppDataSettingsDirectory" untergeordnet. Ebenso können vordefinierte Elemente (wie einen Punkt vorher erwähnt) als Parent-Elemente festgelegt werden (Wie beim Directory-Element "SettingsDirectory"). Abhängig davon, ob es ein Parent-Element gibt oder nicht, gibt der Pfad nur einen einzelnen Ordner-/Dateinamen oder einen vollständigen Pfad an. Das heißt, bei Elementen mit Parent-Elementen setzt sich der Pfad ausSystem.IO.Path.Combine(ÜbergeordneterPfad, DieserPfad)
zusammen. Das Parent-Element muss immer vor dem untergeordneten Element angegeben werden. Befindet sich ein Parent-Element unterhalb des untergeordneten Elementes, führt das zur Laufzeit zu einer NullReferenceException, weil die Properties in der Reihenfolge instanziert werden, in der sie im XML-Schema stehen. - Path:
Der Pfad eines Elementes kann unterschiedlich angegeben sein. Wenn das Element Unterelemente besitzt (bezieht sich auf das XML-Schema selbst und nicht auf Elemente, auf die mit einem Attribut verwiesen wird), muss der Pfad durch ein Attribut namens "Path" angegeben werden. Ansonsten kann der Pfad als Hauptinhalt angegeben werden, wie zum Beispiel beim File-Element "TestTextFile".
Bei SpecialDirectory-Elementen wird anstelle eines tatsächlichen Pfades ein Wert aus dem Enum System.Environment.SpecialFolder verwendet. Der Pfad ergibt sich dann ausSystem.Environment.GetFolderPath(Ordnerbezeichnung)
.
Korrekterweise müsste man bei Elementen, die ein Parent-Element besitzen, "DirectoryName" bzw. "FileName" anstelle von "Path" verwenden, aber dadurch würde man sich mehr Schlüsselwörter merken müssen.
Anwendung:
Im entsprechenden Projekt muss ein Verweis auf die ApplicationSettings.dll hinzugefügt werden. Dann wird in einer Methode, die Funktion
ApplicationSettings.Generator.CreateSettingsAssembly()
aufgerufen. Der erste Parameter gibt den Pfad an, an dem die generierte Dll abgelegt werden soll. Der Dateiname muss die Erweiterung ".dll" haben. Der zweite Parameter ist ein System.Xml.Linq.XElement. Solche Elemente können in Visual Basic bequem im Code hingeschrieben werden. Es ist aber auch möglich, den Inhalt einer XML-Datei zu laden und diesen zu verwenden.Der Code muss einmal ausgeführt werden, dann kann er auskommentiert werden.
Die generierte Dll kann jetzt optional in den gewünschten Ordner verschoben werden, wenn dieser nicht dem angegebenen Pfad entspricht, aber ich empfehle, den Pfad von vornherein richtig zu wählen, weil dann nicht bei jeder Änderung die Dll neu kopiert werden muss.
Anschließend wird ein Verweis auf diese generierte Dll hinzugefügt. Jetzt kann die Dll verwendet werden.
Jetzt ist es vom Vorteil, wenn das äußerste Element den selben Namen hat, wie der Standard-NameSpace des Projektes. Denn dadurch ist die Settings-Klasse direkt aufrufbar und man spart sich die Angabe bzw. den Import des NameSpaces.
Jetzt müssen beim Starten der Anwendung (zum Beispiel im Konstruktor der Startform) die Einstellungen geladen werden. Das geschieht in zwei Schritten:
Zuerst muss die IO-Klasse initialisiert werden, damit sie die Pfade korrekt zusammenstellen kann. Dazu muss ihr der Dateipfad zur ausgeführten Datei übergeben werden. Das ist üblicherweise
System.Windows.Forms.Application.ExecutablePath
.Im zweiten Schritt werden die Einstellungen aus der XML-Datei gelesen. Dazu wird der Pfad zur XML-Datei benötigt. Es bietet sich an, in der IO-Klasse eine Property für diesen Pfad anzulegen (beispielsweise den Programmordner oder unter AppData\Local einen Unterordner). Natürlich funktionieren auch alle anderen Pfade. Möglicherweise funktionieren beim Laden auch URLs.
Man beachte, dass die Properties in der IO-Klasse keine Strings sondern eigene Klassen sind, die das Arbeiten damit erleichtern. Deshalb muss vom Objekt, das von der SettingsXmlFile-Property zurückgegeben wird, die Path-Property abgerufen werden.
Beim Beenden der Anwendung (z.B. OnClosing) müssen die Einstellungen wieder gespeichert werden.
Dazu muss ebenfalls der Pfad zur XML-Datei angegeben werden:
Nun können die Einstellungen verwendet werden. Beispiele:
VB.NET-Quellcode
- Public Sub New()
- InitializeComponent()
- Settings.IO.Initialize(Application.ExecutablePath)
- Settings.Load(Settings.IO.SettingsXmlFile.Path)
- End Sub
- Protected Overrides Sub OnShown(e As System.EventArgs)
- Me.Text = Settings.MainWindow.WindowTitle
- Me.BackColor = Settings.MainWindow.BackGroundColor
- TextBox_SyntaxHighlighting.Text = Settings.MainWindow.CodeWindow.SyntaxHighlighting
- CheckBox_UseDebugWindow.Checked = Settings.DebugWindow.InUse
- MyBase.OnShown(e)
- End Sub
- Protected Overrides Sub OnClosing(e As System.ComponentModel.CancelEventArgs)
- Settings.MainWindow.WindowTitle = Me.Text
- Settings.MainWindow.BackGroundColor = Me.BackColor
- Settings.MainWindow.CodeWindow.SyntaxHighlighting = TextBox_SyntaxHighlighting.Text
- Settings.DebugWindow.InUse = CheckBox_UseDebugWindow.Checked
- Settings.Save(Settings.IO.SettingsXmlFile.Path)
- MyBase.OnClosing(e)
- End Sub
Download:
ApplicationSettings v1.2.zip (23KB gepackt, 56.5KB entpackt)
ApplicationSettings.xml (12.3KB) (XML-Doku für Wiederverwendung)
Lizenz/Weitergabe:
Darf beliebig weitergegeben werden, solange dafür kein Geld verlangt wird.
Einkompilieren erlaubt (Erwähnung wäre nett).
Dekompilieren erlaubt, ich beantworte Fragen zum Code aber auch gerne selbst.
"Luckily luh... luckily it wasn't poi-"
-- Brady in Wonderland, 23. Februar 2015, 1:56
Desktop Pinner | ApplicationSettings | OnUtils
-- Brady in Wonderland, 23. Februar 2015, 1:56
Desktop Pinner | ApplicationSettings | OnUtils
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Niko Ortner“ ()