Overview
NSettings is a lightweight library for persisting application settings.
Author's Note - Although many frameworks already exist for working with settings, most are complicated or over engineered for simple usage scenarios. I reluctantly created NSettings because I needed a library that satisfied these specific needs:
- The public API is simple and obvious.
- The dependencies and runtime footprint are as small as possible.
- Settings are key/value pairs and the keys may optionally be saved in named groups.
- The backing storage is customisable (see next section).
This small example shows how a program can remember how many times it has been run by storing a counter in the settings.
var settings = new RegistrySettings();
int runCount = settings.GetInt(null, "RunCount", 0);
Console.WriteLine($"This is run number {++runCount} (saving the value now)");
settings.Put(null, "RunCount", runCount);
There are many simple and convenient methods to Put and Get commonly used types using the NSettings library. Nullable types and defaults are easy to handle thanks to convenient method overloads.
int n1 = settings.GetInt(null, "MyNumber", 123456); // A default value if not found
int? n2 = settings.GetInt(null, "YourNumber"); // Null if not found
NOTE: You can write more robust and flexible code by using the C# nameof keyword to specify the names of the keys for the method calls.
public long HashCode { get; set; }
:
HashCode = settings.GetLong(null, nameof(HashCode), 0L);
The NSettings Library is designed to be extensible so that any type of backing storage can persist the settings. The core library and its NuGet package currently contain two implementing classes: one uses a single XML file as the backing storage, the other uses the Windows registry.
Implementations
XmlFileSettings
Constructor: XmlFileSettings(string backingFilename)
This class implements backing storage for settings using a single XML document file. Because the whole XML file is rewritten each time the contents change, it is not suitable for persisting large numbers of settings, or for settings that are frequently updated.
RegistrySettings
Constructor: RegistrySettings()
Constructor: RegistrySettings(string company, string product, string version)
This class implements backing storage for settings using a local registry key. The company name, product name and version are combined to create a full key path in this format:
HKEY_CURRENT_USER\Software\company\product version
The version must be specified as a "x.y" pair of dot-separated major and minor version numbers. If the empty constructor is used or any of the constructor arguments are null then an attempt is made to find a default value for the null argument in the assembly attributes, searching in sequence: (1) The Entry assembly (2) The Executing assembly (3) The Calling assembly.
Supported Types
The settings library can round-trip all types that have a TypeConverter that can convert them to-and-from a string representation. Such types include String, Guid and all of the numeric and date types and their nullable equivalents.
Commonly used types such as byte[]
and string[]
do not have useful converters so the library treats them as special cases and round-trips them correctly.
A user defined type that is associated with a two-way string converter will be round-tripped correctly by the library. A sample class is provided in the unit test project.
Usage
The library methods for updating values take one of the following forms:
Put ( group , key , value )
GetType ( group , key )
GetType ( group , key , Type fallback )
Get<T> ( group , key , T fallback )
DeleteGroup ( group )
DeleteKey ( group , key )
The group is used to optionally group many keys together allowing them to be listed or deleted in groups. The group can be null, in which case the keys are placed into an unnamed group. Groups only exist to optionally help manage large numbers of keys, so in most simple usage cases the group can be null.
The key uniquely identifies a value stored in a group of settings. The (group,key) pair effectively form a compound key.
The methods with a fallback argument are used to retrieve non-nullable value types.
The group and key arguments to all methods are objects, so anything that can be converted to a string can be used as a part of the key. It is recommended that the C# nameof keyword be used to specify key names.
Sample Code
Put values into the settings. In this sample we assume the the MyClass class has a TypeConverter associated with it to allow it to be converted to and from a string representation. The unit test source code contains an example class with a TypeConverter.
int prime = 7837703;
Guid id = Guid.NewGuid();
string message = "Hello world!";
MyClass mc = new MyClass();
var settings = new RegistrySettings();
settings.Put(null, nameof(prime), prime);
settings.Put(null, nameof(id), id);
settings.Put(null, nameof(message), message);
settings.Put(null, nameof(mc), mc);
Get values from the settings. The GetInt and GetGuid methods are returning non-nullable value types so the overloads that take a default fallback value are required.
prime = settings.GetInt(null, nameof(prime), 0);
id = settings.GetGuid(null, nameof(id), Guid.Empty);
message = settings.Get(null, nameof(message));
mc = settings.Get<MyClass>(null, nameof(mc), null);
Get nullable values from the settings. There are overloads that have no default fallback for values types, so they have Nullable<> return values.
int? number = settings.GetInt(null, "My Number");
Guid? uuid = settings.GetGuid(null, "My Guid");
double? scale = settings.GetDouble(null, "Scale");
DateTime? time = settings.GetDateTime(null, "StartTime");
The following code shows how to list all settings using a double nested loop over the groups and their keys and values. If any values have been stored in the unnamed (null) group then one of the group names will be a null string.
foreach (string group in settings.ListGroups())
{
Console.WriteLine("Group {0}", group ?? "Unnamed (null) Group");
foreach (string name in settings.ListKeys(group))
{
Console.WriteLine(" Key {0} = {1}", group, settings.Get(group, name));
}
}
Notes
📙 string[] Support
The Windows Registry does not support storing string arrays with null elements. The workaround is to roundtrip null elements as the special token __nil__
. A NotSupportedException is thrown if an attempt is made to save a string array with an element equal to the token string.
📙 Type Conversion
Attempting to get a settings value as a type that differs from the type of the value that was put may result in unpredictable runtime exceptions. For example, getting an Int32 value as a DateTime will certainly produce a cast error; however, getting an Int64 value as an Int32 may randomly fail depending upon the size of the number. Always use a consistent type for each setting key.
Note that The Get
method will never fail, it simply returns the internal representation of a key's value as a culture neutral string.
📙 Documentation
The NSettings projects and source code are free and in the public domain for educational or utility use by anyone. Please report bugs or enhancements to the author. Source code documentation generated by Sandcastle is available via this link:
📘 https://orthoprog.blob.core.windows.net/dochelp/nsettings/index.html