Wednesday, September 10, 2008

Saving global variables to an XML file

The block below is from the book Programming Microsoft Visual Basic 2005, which is an excellent book and should be on every VB Programmers shelf:

Here's a practical example of a technique that I used in several real applications. I gather all the global variables in a class named something like Globals or ProjectData that I can persist to an XML file stored on disk. To leverage the XML serialization mechanism offered by the .NET Framework, these global variables must be implemented as instance fields, but at the same time the class must be exposed as a singleton so that it can be accessed from anywhere in the application. Here's how you can build such a class:

' This code requires a reference to the System.Xml.dll assembly.

' (Classes must be public to use XML serialization.)
Public Class Globals
' This singleton instance is created when the application is created.
Private Shared m_Value As New Globals

' This static read-only property returns the singleton instance.
Public Shared ReadOnly Property Value() As Globals
Return m_Value
End Get
End Property

' Load the singleton instance from file.
Public Shared Sub Load(ByVal fileName As String)
' Deserialize the content of this file into the singleton object.
Using fs As New FileStream(fileName, FileMode.Open)
Dim xser As New XmlSerializer(GetType(Globals))
m_Value = DirectCast(xser.Deserialize(fs), Globals)
End Using
End Sub

' Save the singleton instance to file.
Public Shared Sub Save(ByVal fileName As String)
' Serialize the singleton object to the file.
Using fs As New FileStream(fileName, FileMode.Create)
Dim xser As New XmlSerializer(GetType(Globals))
xser.Serialize(fs, m_Value)
End Using
End Sub

' Instance fields (the global variables)
Public UserName As String
Public Documents() As String
Public UseSimplifiedMenus As Boolean = True
Public UseSpellChecker As Boolean = True
End Class

Using the Globals class is straightforward because you must simply invoke the Load static method after the application starts and the Save static method before the application terminates. All the global variables can be accessed as properties of the Globals.Value object, as follows:

Globals.Value.UserName = "Francesco"
' Assign two items to the Documents array.
Globals.Value.Documents = New String(){"c:\doc1.txt", "c:\doc2.txt"}
' Save current global variables on disk.


Interestingly, the very first time a given user runs the application, the XML file doesn't exist, thus the singleton Globals object will contain the default values for global variables you've defined by means of initializers.


Visual Basic 2005 comes with a very powerful mechanism for saving and retrieving user settings, which is conceptually similar to the one I illustrate in this section. You can read more about it in Chapter 16, "The My Namespace." However, the technique I just illustrated is more generic and flexible than the built-in Visual Basic mechanism is and can be used in many circumstances in which the built-in approach wouldn't work. For one, the built-in technique can store only one set of values for each user, and you can't manage multiple sets of preferences for a given user, merge current options with other users, move options to other computers, and so forth.

No comments: