
Introduction
This article introduces a class that simplifies the process of saving and restoring
application settings. The Savior
class has four static methods that enable
saving and reading application settings using the system registry or a binary
serialization file. All the methods work with a user-defined object that encapsulates
all of the settings and their default values. In the examples, this user-defined
class is called Settings
. To save the application settings to the registry,
the programmer simply sets any values in the Settings
object and
then calls the Savior.Save(settings)
method. Reading the settings
is equally simple, as is reading or saving to a file.
Background
Saving and restoring application settings is a tedious part of almost any software
project. The .NET Framework provides a simple facility for binary serialization to and
from a file. Unfortunately, the registry is more cumbersome, especially for data types
other than strings, integers, and byte arrays. The Savior
class uses
reflection to automatically save and restore objects to the registry, as well as
providing a thin wrapper around the binary serialization methods to simplify this
process as well.
For example, to save a Font
object to the registry without
Savior
, one has to figure out a method to store the necessary
information in strings, integers, or bytes and then read it back later. Using
Savior
, one simply defines a Font
object within the
Settings
class and the rest is handled automatically.
Savior
supports the following data types. Additional types can
easily be added as needed.
Supported data types:
-
string
-
bool
-
decimal
-
int
-
float
-
double
-
Color
-
Point
-
Size
-
Font
-
DateTime
-
TimeSpan
-
int[]
-
byte[]
-
string[]
-
bool[]
-
float[]
-
double[]
as well as any enum
class.
Using the code
The demonstration project gives an elaborate example showing the use of many
different data types. Here we will just show how to save and restore the location
and background color of a form.
First, create a Settings
class containing the desired data:
[Serializable]
public class Settings
{
public Color BackColor = Color.Aqua;
public Point Location = new Point(100,100);
}
Note that both BackColor
and Location
are given default
values within the class definition. Also note that the class has been given the
[Serializable]
attribute. This is necessary for file serialization.
Saving the location and color of MyForm
to the registry now requires
only the following code:
Settings settings = new Settings();
settings.BackColor = MyForm.BackColor;
settings.Location = MyForm.Location;
Savior.Save(settings,"Software\\Ultrapico\\Savior");
In this case, one of several overloaded versions of the
Savior.Save()
method is used. This one stores the information in
HKEY_CURRENT_USER\Software\Ultrapico\Savior
.
Reading settings is equally simple:
Savior.Read(settings,"Software\\Ultrapico\\Savior");
MyForm.BackColor = settings.BackColor;
MyForm.Location = settings.Location;
To save and restore using a binary serialization file, use the following code:
Savior.SaveToFile(settings,FileName);
...
settings = (Settings)Savior.ReadFromFile(FileName);
Note the different syntax of the ReadFromFile()
and
Read()
methods. The ReadFromFile()
method returns a
Settings
object, but it must be explicitly cast to the proper type.
Summary of methods
Here is a complete list of the methods provided by the Savior class:
-
void Save(Settings)
--> Saves the settings to the default registry key
-
void Save(Settings,string)
--> Saves the settings to a specified key name in
HKCU
-
void Save(Settings,RegistryKey)
--> Saves the settings to a specified registry key
-
void SaveToFile(Settings,string)
--> Saves the settings to a specified file
-
void Read(Settings)
--> Reads the settings from the default registry key
-
void Read(Settings,string)
--> Reads the settings from a specified key name in
HKCU
-
void Read(Settings,RegistryKey)
--> Reads the settings from a specified registry key
-
object ReadFromFile(string)
--> Reads the settings from a specified file
-
string ToString(Settings)
--> Returns information about the settings
Under the hood
Savior
makes extensive use of object reflection to read and save data to
the registry. Here is a slightly simplified excerpt from the Save()
method illustrating how it works:
foreach(FieldInfo fi in settings.GetType().GetFields())
{
switch (fi.FieldType.Name.ToLower())
{
case "string":
Key.SetValue(fi.Name,(string)fi.GetValue(settings));
break;
case "point":
Point point=(Point)fi.GetValue(settings);
Key.SetValue(fi.Name+".X",point.X);
Key.SetValue(fi.Name+".Y",point.Y);
break;
case "color":
Key.SetValue(fi.Name,((Color)fi.GetValue(settings)).Name);
break;
...
The method uses reflection to iterate through all fields in the Settings
class. The type of each field is used to determine how to save the data in the registry.
For example, as the code above shows, a Point
named Location
would be stored in the registry as a pair of string values whose names are
Location.X
and Location.Y
. The Read()
method works in a similar way.
The demonstration program
The demonstration program shows how numerous settings can be saved and restored
using Savior
. Among other things, it shows how to save the settings of a
ListView
control including the column headings, column order, and column widths.
The tricky part of this is keeping track of the column order, which is done using
Interop. Special thanks to dfontanesi on The Code Project, for his article "Persisting ListView settings with serialization".
The ListViewSettings
class used in the demonstration project uses
a simplified version of his class.