Imports System.IO Imports System.Xml.Serialization Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Filesystem Imports System.Xml 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 _CurrentDataPath As String ''' ''' The blueprint class from which the default config is created ''' Private ReadOnly _Blueprint 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) _Blueprint = Activator.CreateInstance(Of T) _Serializer = New XmlSerializer(_Blueprint.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 _File.TestPathIsDirectory(UserConfigPath) Then Throw New ArgumentException($"Path {UserConfigPath} is not a directory!") End If If Not _File.TestPathIsDirectory(ComputerConfigPath) Then Throw New ArgumentException($"Path {ComputerConfigPath} is not a directory!") End If _Config = LoadConfig() End Sub ''' ''' Save the current config object to `UserConfigPath` ''' Public Sub Save() WriteToFile(_Config, _UserPath) End Sub ''' ''' First check if a user config exists and if it does, load it. ''' If not, check if a systemwide config exists and and if it does, load it. ''' Otherwise, create a user config using the default values from the supplied config class `T` ''' ''' Private Function LoadConfig() As T Dim oConfig As T If IO.File.Exists(_UserPath) Then _Logger.Debug("Loading config from UserPath: {0}", _UserPath) _CurrentDataPath = _UserPath oConfig = ReadFromFile(_UserPath) ElseIf IO.File.Exists(_ComputerPath) Then _Logger.Debug("Loading config from ComputerPath: {0}", _ComputerPath) _CurrentDataPath = _ComputerPath oConfig = ReadFromFile(_ComputerPath) Else _Logger.Debug("Creating default config in UserPath: {0}", _UserPath) _CurrentDataPath = _UserPath oConfig = Activator.CreateInstance(_Blueprint.GetType) WriteToFile(_Config, _UserPath) End If Return oConfig End Function ''' ''' 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