From 9ee59ac4009c304da242805667a13c26cb673103 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Wed, 13 Feb 2019 15:19:09 +0100 Subject: [PATCH] Config Manager WIP --- Config/Config.vbproj | 9 +- Config/ConfigManager.vb | 142 +++++++++++++++++++++ Config/{BaseConfig.vb => OldConfig.vb} | 2 +- Config/SinceVersionAttribute.vb | 9 ++ Filesystem/File.vb | 2 +- TestGUI/ConfigTest.Designer.vb | 62 +++++++++ TestGUI/ConfigTest.resx | 120 +++++++++++++++++ TestGUI/ConfigTest.vb | 25 ++++ TestGUI/Form1.Designer.vb | 12 ++ TestGUI/Form1.vb | 1 + TestGUI/My Project/Application.Designer.vb | 2 +- TestGUI/My Project/Application.myapp | 2 +- TestGUI/My Project/app.manifest | 76 +++++++++++ TestGUI/TestGUI.vbproj | 17 +++ 14 files changed, 476 insertions(+), 5 deletions(-) create mode 100644 Config/ConfigManager.vb rename Config/{BaseConfig.vb => OldConfig.vb} (98%) create mode 100644 Config/SinceVersionAttribute.vb create mode 100644 TestGUI/ConfigTest.Designer.vb create mode 100644 TestGUI/ConfigTest.resx create mode 100644 TestGUI/ConfigTest.vb create mode 100644 TestGUI/My Project/app.manifest diff --git a/Config/Config.vbproj b/Config/Config.vbproj index 4794b3ff..e1d2d6a4 100644 --- a/Config/Config.vbproj +++ b/Config/Config.vbproj @@ -54,6 +54,7 @@ + @@ -72,7 +73,8 @@ - + + True @@ -88,6 +90,7 @@ Settings.settings True + @@ -110,6 +113,10 @@ + + {991d0231-4623-496d-8bd0-9ca906029cbc} + Filesystem + {903b2d7d-3b80-4be9-8713-7447b704e1b0} Logging diff --git a/Config/ConfigManager.vb b/Config/ConfigManager.vb new file mode 100644 index 00000000..08672da4 --- /dev/null +++ b/Config/ConfigManager.vb @@ -0,0 +1,142 @@ +Imports System.IO +Imports System.Xml.Serialization +Imports DigitalData.Modules.Logging +Imports DigitalData.Modules.Filesystem + +Public Class ConfigManager(Of T) + Private Const USER_CONFIG_NAME As String = "UserConfig.xml" + Private Const COMPUTER_CONFIG_NAME As String = "ComputerConfig.xml" + + Private ReadOnly _LogConfig As LogConfig + Private ReadOnly _Logger As Logger + Private ReadOnly _File As Filesystem.File + Private ReadOnly _UserPath As String + Private ReadOnly _ComputerPath As String + Private ReadOnly _CurrentDataPath As String + + Private ReadOnly _Schema As T + Private ReadOnly _Serializer As XmlSerializer + + Public ReadOnly Property Config As T + + ''' + ''' Creates a new instance of the ConfigManager + ''' + ''' + ''' Public Class Config + ''' Public Property StringEntry As String = "TEST" + ''' Public Property BoolEntry As Boolean = True + ''' Public Property IntEntry As Integer = 123 + ''' End Class + ''' + ''' Dim oConfigManager = New ConfigManager(Of Config)(_LogConfig, Application.UserAppDataPath, Application.CommonAppDataPath) + ''' + ''' LogConfig instance + ''' The first path to check for a config file, eg. AppData + ''' The second path to check for a config file, eg. ProgramData + Public Sub New(LogConfig As LogConfig, UserConfigPath As String, ComputerConfigPath As String) + _LogConfig = LogConfig + _Logger = LogConfig.GetLogger() + _File = New Filesystem.File(_LogConfig) + + _UserPath = Path.Combine(UserConfigPath, USER_CONFIG_NAME) + _ComputerPath = Path.Combine(ComputerConfigPath, COMPUTER_CONFIG_NAME) + + _Schema = Activator.CreateInstance(Of T) + _Serializer = New XmlSerializer(_Schema.GetType) + + If Not Directory.Exists(UserConfigPath) Then + Throw New DirectoryNotFoundException($"Path {UserConfigPath} does not exist!") + End If + + If Not Directory.Exists(ComputerConfigPath) Then + Throw New DirectoryNotFoundException($"Path {ComputerConfigPath} does not exist!") + End If + + If Not Filesystem.File Then Then + Throw New DirectoryNotFoundException() + End If + + If IO.File.Exists(_UserPath) Then + _Logger.Debug("Loading config from UserPath: {0}", _UserPath) + _CurrentDataPath = _UserPath + _Config = ReadFromFile(_UserPath) + ElseIf IO.File.Exists(_ComputerPath) Then + _Logger.Debug("Loading config from ComputerPath: {0}", _ComputerPath) + _CurrentDataPath = _ComputerPath + _Config = ReadFromFile(_ComputerPath) + Else + _Logger.Debug("Creating default config in UserPath: {0}", _UserPath) + _CurrentDataPath = _UserPath + _Config = Activator.CreateInstance(_Schema.GetType) + + WriteToFile(_Config, _UserPath) + End If + End Sub + + ''' + ''' Save the current config object to `UserConfigPath` + ''' + Public Sub Save() + WriteToFile(_Config, _UserPath) + End Sub + + ''' + ''' Serialize a config object to byte array + ''' + ''' + ''' + Private Function Serialize(Data As T) As Byte() + Try + _Logger.Debug("Serializing config object") + + Using oStream = New MemoryStream() + _Serializer.Serialize(oStream, Data) + Return oStream.ToArray() + End Using + Catch ex As Exception + _Logger.Error(ex) + Throw ex + End Try + End Function + + ''' + ''' Write an object to disk as xml + ''' + ''' The object to write + ''' The file name to write to + Private Sub WriteToFile(Data As T, Path As String) + Try + _Logger.Debug("Saving config to: {0}", Path) + Dim oBytes = Serialize(Data) + + Using oFileStream = New FileStream(Path, FileMode.Create, FileAccess.Write) + oFileStream.Write(oBytes, 0, oBytes.Length) + oFileStream.Flush() + End Using + Catch ex As Exception + _Logger.Error(ex) + Throw ex + End Try + End Sub + + ''' + ''' Reads an xml from disk and deserializes to object + ''' + ''' + Private Function ReadFromFile(Path As String) As T + Try + _Logger.Debug("Loading config from: {0}", Path) + Dim oConfig As T + + Using oReader As New StreamReader(Path) + oConfig = _Serializer.Deserialize(oReader) + End Using + + Return oConfig + Catch ex As Exception + _Logger.Error(ex) + Throw ex + End Try + End Function +End Class diff --git a/Config/BaseConfig.vb b/Config/OldConfig.vb similarity index 98% rename from Config/BaseConfig.vb rename to Config/OldConfig.vb index 4e909d06..608cbd4d 100644 --- a/Config/BaseConfig.vb +++ b/Config/OldConfig.vb @@ -1,7 +1,7 @@ Imports System.IO Imports DigitalData.Modules.Logging -Public MustInherit Class BaseConfig +Public MustInherit Class OldConfig Private Const _userConfigFileName As String = "UserConfig.xml" Private _logFactory As LogConfig Private _logger As Logger diff --git a/Config/SinceVersionAttribute.vb b/Config/SinceVersionAttribute.vb new file mode 100644 index 00000000..f3b94c7e --- /dev/null +++ b/Config/SinceVersionAttribute.vb @@ -0,0 +1,9 @@ +Public Class SinceVersionAttribute + Inherits Attribute + + Public Version As Version + + Public Sub New(Version As String) + Me.Version = New Version(Version) + End Sub +End Class \ No newline at end of file diff --git a/Filesystem/File.vb b/Filesystem/File.vb index 4d02582f..d11c27c8 100644 --- a/Filesystem/File.vb +++ b/Filesystem/File.vb @@ -94,7 +94,7 @@ Public Class File IO.File.Move(FilePath, Path.Combine(Directory, oFileInfo.Name)) End Sub - Private Function TestPathIsDirectory(Path As String) As Boolean + Public Function TestPathIsDirectory(Path As String) As Boolean Dim oIsDirectory As Boolean = (System.IO.File.GetAttributes(Path) And FileAttributes.Directory) = FileAttributes.Directory Return oIsDirectory End Function diff --git a/TestGUI/ConfigTest.Designer.vb b/TestGUI/ConfigTest.Designer.vb new file mode 100644 index 00000000..5d46d129 --- /dev/null +++ b/TestGUI/ConfigTest.Designer.vb @@ -0,0 +1,62 @@ + _ +Partial Class ConfigTest + Inherits System.Windows.Forms.Form + + 'Das Formular überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen. + _ + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + 'Wird vom Windows Form-Designer benötigt. + Private components As System.ComponentModel.IContainer + + 'Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich. + 'Das Bearbeiten ist mit dem Windows Form-Designer möglich. + 'Das Bearbeiten mit dem Code-Editor ist nicht möglich. + _ + Private Sub InitializeComponent() + Me.Button1 = New System.Windows.Forms.Button() + Me.Button2 = New System.Windows.Forms.Button() + Me.SuspendLayout() + ' + 'Button1 + ' + Me.Button1.Location = New System.Drawing.Point(119, 76) + Me.Button1.Name = "Button1" + Me.Button1.Size = New System.Drawing.Size(149, 45) + Me.Button1.TabIndex = 0 + Me.Button1.Text = "LoadConfig" + Me.Button1.UseVisualStyleBackColor = True + ' + 'Button2 + ' + Me.Button2.Location = New System.Drawing.Point(429, 86) + Me.Button2.Name = "Button2" + Me.Button2.Size = New System.Drawing.Size(75, 23) + Me.Button2.TabIndex = 1 + Me.Button2.Text = "SaveConfig" + Me.Button2.UseVisualStyleBackColor = True + ' + 'ConfigTest + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(800, 450) + Me.Controls.Add(Me.Button2) + Me.Controls.Add(Me.Button1) + Me.Name = "ConfigTest" + Me.Text = "ConfigTest" + Me.ResumeLayout(False) + + End Sub + + Friend WithEvents Button1 As Button + Friend WithEvents Button2 As Button +End Class diff --git a/TestGUI/ConfigTest.resx b/TestGUI/ConfigTest.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/TestGUI/ConfigTest.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestGUI/ConfigTest.vb b/TestGUI/ConfigTest.vb new file mode 100644 index 00000000..8e0dbbc7 --- /dev/null +++ b/TestGUI/ConfigTest.vb @@ -0,0 +1,25 @@ +Imports DigitalData.Modules.Config +Imports DigitalData.Modules.Logging + +Public Class ConfigTest + Private _LogConfig As LogConfig + Private _config As ConfigManager(Of Config) + Private _FilePath As String = IO.Path.Combine(Application.LocalUserAppDataPath, "UserConfig.xml") + + Private Sub ConfigTest_Load(sender As Object, e As EventArgs) Handles MyBase.Load + _LogConfig = New LogConfig(LogConfig.PathType.AppData) + _config = New ConfigManager(Of Config)(_LogConfig, Application.UserAppDataPath, Application.CommonAppDataPath) + End Sub + + Public Class Config + + Public Property StringEntry As String = "TEST" + Public Property BoolEntry As Boolean = True + Public Property IntEntry As Integer = 123 + End Class + + Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click + _config.Config.IntEntry = 999 + _config.Save() + End Sub +End Class \ No newline at end of file diff --git a/TestGUI/Form1.Designer.vb b/TestGUI/Form1.Designer.vb index ece45d55..f4812171 100644 --- a/TestGUI/Form1.Designer.vb +++ b/TestGUI/Form1.Designer.vb @@ -45,6 +45,7 @@ Partial Class Form1 Me.Label6 = New System.Windows.Forms.Label() Me.Button4 = New System.Windows.Forms.Button() Me.LookupControl1 = New DigitalData.Controls.LookupGrid.LookupControl() + Me.Button6 = New System.Windows.Forms.Button() CType(Me.GridControl1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.GridView1, System.ComponentModel.ISupportInitialize).BeginInit() Me.SuspendLayout() @@ -242,11 +243,21 @@ Partial Class Form1 Me.LookupControl1.Size = New System.Drawing.Size(270, 23) Me.LookupControl1.TabIndex = 23 ' + 'Button6 + ' + Me.Button6.Location = New System.Drawing.Point(764, 308) + Me.Button6.Name = "Button6" + Me.Button6.Size = New System.Drawing.Size(75, 23) + Me.Button6.TabIndex = 24 + Me.Button6.Text = "Button6" + Me.Button6.UseVisualStyleBackColor = True + ' 'Form1 ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.ClientSize = New System.Drawing.Size(1050, 487) + Me.Controls.Add(Me.Button6) Me.Controls.Add(Me.LookupControl1) Me.Controls.Add(Me.Button4) Me.Controls.Add(Me.Label6) @@ -300,4 +311,5 @@ Partial Class Form1 Friend WithEvents Label6 As Label Friend WithEvents Button4 As Button Friend WithEvents LookupControl1 As DigitalData.Controls.LookupGrid.LookupControl + Friend WithEvents Button6 As Button End Class diff --git a/TestGUI/Form1.vb b/TestGUI/Form1.vb index 1103eed8..7b2dcde6 100644 --- a/TestGUI/Form1.vb +++ b/TestGUI/Form1.vb @@ -169,4 +169,5 @@ Public Class Form1 bw1.RunWorkerAsync() End Sub + End Class diff --git a/TestGUI/My Project/Application.Designer.vb b/TestGUI/My Project/Application.Designer.vb index b30e1dba..716d1571 100644 --- a/TestGUI/My Project/Application.Designer.vb +++ b/TestGUI/My Project/Application.Designer.vb @@ -32,7 +32,7 @@ Namespace My _ Protected Overrides Sub OnCreateMainForm() - Me.MainForm = Global.TestGUI.FolderWatcher + Me.MainForm = Global.TestGUI.ConfigTest End Sub End Class End Namespace diff --git a/TestGUI/My Project/Application.myapp b/TestGUI/My Project/Application.myapp index d87a023e..75bf29f8 100644 --- a/TestGUI/My Project/Application.myapp +++ b/TestGUI/My Project/Application.myapp @@ -1,7 +1,7 @@  true - FolderWatcher + ConfigTest false 0 true diff --git a/TestGUI/My Project/app.manifest b/TestGUI/My Project/app.manifest new file mode 100644 index 00000000..ef881eb8 --- /dev/null +++ b/TestGUI/My Project/app.manifest @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestGUI/TestGUI.vbproj b/TestGUI/TestGUI.vbproj index e0b1a238..4a719fb0 100644 --- a/TestGUI/TestGUI.vbproj +++ b/TestGUI/TestGUI.vbproj @@ -46,6 +46,9 @@ On + + My Project\app.manifest + @@ -93,6 +96,12 @@ + + ConfigTest.vb + + + Form + FolderWatcher.vb @@ -123,6 +132,9 @@ + + ConfigTest.vb + FolderWatcher.vb @@ -138,6 +150,7 @@ + MyApplicationCodeGenerator Application.Designer.vb @@ -154,6 +167,10 @@ + + {44982f9b-6116-44e2-85d0-f39650b1ef99} + Config + {991d0231-4623-496d-8bd0-9ca906029cbc} Filesystem