SettingsAdapterFactory class
Generates a dynamic implementation of an interface with properties that binds to a settings store and implements INotifyPropertyChanged.
It only takes about 4 minutes to read this page.
The problem
Storing application settings and simple access of it are often boring work. You just want to note a few values for the next application start and not bother with all aspects of the different data types, error handling, and program updates. The obvious solution is simply serialising a quickly written data class and saving it anywhere.
While that is quite easy, it comes with a number of issues. You have no control over the storage format. .NET serialises data so that it can be read again right after. But when the structure of the settings changes with a new program version the existing settings may not be readable at all anymore in the worst case. External access to the data or hand-editing or using a universal configuration editor like “about:config” in Firefox is also problematic. And saving the data in the Windows registry instead of files is hardly possible. The error conditions that show up in the field require special precautions to warrant a high level of reliability.
If on top of that the settings shall be used in an interactive user interface the system should also notify changes to the saved settings so that the UI can react on it. Often, applications simply need to be restarted to really apply all settings.
The solution
This factory class relieves the programmer of this complexity almost completely and gives back full flexibility as soon as he asks for it. Therefore the definition of the application settings data structure is reduced to the smallest possible form: Instead of classes with written-out properties you just define interfaces. The properties in these interfaces only determine the name and data type at first, not the behaviour. Default values can be set through attributes. Properties of an interface type themselves serve the hierarchical organisation of the settings. Interfaces can be reused for recurring structures. There are some practical helper methods available for IWindowStateSettings
.
The entire system is composed of two parts that complement each other in layers. The SettingsAdapterFactory
class does the cumbersome work of implementing the concisely defined interface and fill it with the desired behaviour. For every property, a getter and setter is created which retrieves the value from the storage back-end or puts it back there. The various interfaces are connected automatically. Change notifications for INotifyPropertyChanged
are also passed through from the back-end. All that happens at runtime with reflection and IL code generating so that no additional build steps or tools are necessary.
Currently two back-ends are available, both implement the interface ISettingsStore
. FileSettingsStore
is based on the older Settings class that was modernised and slimmed down here. It stores the settings in an XML file. By the way, the file format is still compatible so you can replace the Settings class with this factory solution along with the update code described in the demo application. RegistrySettingsStore
stores settings in the registry, using the customary hierarchy of subkeys and values. Custom back-ends can be created, for example for a client-server architecture.
Your application gets an implementation of the specified interface from the factory and accesses it through that interface. This allows using code editor support of IntelliSense (automatic code completion and documentation), and spelling or type errors are already discovered by the compiler. Direct access on the SettingsStore via the key names is also possible. This can be used for renaming old keys (path names of the properties) into new ones after program updates and convert the old values if necessary.
Thanks to this flexible separation the data store can also be made available to plugins. They just bring their own interfaces and generate their own implementations with the factory, sharing the SettingsStore of the host application with an individual prefix. The demo application also covers this scenario with some sample code.
Compatibility:
Example
The following sample shows an interface definition for application settings:
public interface IAppSettings : ISettings
{
// Gets or sets the last started version of the application.
string LastStartedAppVersion { get; set; }
string[] RecentlyLoadedFiles { get; set; }
bool IsSoundEnabled { get; set; }
// Gets the view-related settings.
IViewSettings View { get; }
}
// Defines view-related application settings.
public interface IViewSettings : ISettings
{
[DefaultValue(true)]
bool MonospaceFont { get; set; }
bool IsWindowOnTop { get; set; }
// Gets the state settings of the main window. This interface is predefined.
IWindowStateSettings MainWindowState { get; }
}
The following sample shows how to use the factory and the settings object. The SettingsHelper
class provides methods to make the program settings handling easier.
new FileSettingsStore(
SettingsHelper.GetAppDataPath(@"Unclassified\SettingsDemo", "SettingsDemo.conf")));
Settings.LastStartedAppVersion = "1.0";
if (Settings.View.RememberLocation)
{
SettingsHelper.BindWindowState(mainWindow, Settings.MainWindowState);
}
Download
master.zipLatest source code directly from GitHub
There’s a public Git repository of SettingsAdapterFactory on GitHub. Changes to the code are documented there.
Licence and terms of use
Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. (GNU All-Permissive licence)
Statistic data
- Created on 2015-02-13, updated on 2015-02-18.
- Ca. 2 100 lines of code, estimated development costs: 2 100 - 8 400 €