C# .NET Registry-based configuration base class

I usually find myself wanting to be able to configure my application without having to change the underlying code. And although Visual Studio allows you to create application settings inside the IDE (saved to a .exe.config file), I would prefer to use the registry to hold my applications configuration.
My solution was to make a base registry configuration class that allows me to create/modify registry keys.
So where do we start?
Lets create our class! I’ll be calling it RegistryConfig
namespace ns_stebo | |
{ | |
public abstract class RegistryConfig | |
{ | |
} | |
} |
Now we have created our class lets add some properties and a constructor.
namespace ns_stebo | |
{ | |
public abstract class RegistryConfig | |
{ | |
public RegistryHive Hive | |
{ | |
get; | |
private set; | |
} | |
public string RootKey | |
{ | |
get; | |
private set; | |
} | |
protected RegistryConfig(RegistryHive hive, string rootKey) | |
{ | |
Hive = hive; | |
RootKey = rootKey; | |
} | |
} | |
} |
So here we have read-only properties that are set from parameters taken by the constructor. Because this is an abstract class we should mark any constructors we make as either protected
or private
.
The methods
So now we have to add a few methods! Firstly I shall add a function for parsing the Hive property that was set when the class was initialized. This function will return a RegistryKey
object that we can use to access and the RootKey
and the values in that subkey.
protected RegistryKey GetRegistryKey() | |
{ | |
switch (Hive) | |
{ | |
case RegistryHive.ClassesRoot: | |
return Registry.ClassesRoot; | |
case RegistryHive.CurrentConfig: | |
return Registry.CurrentConfig; | |
case RegistryHive.CurrentUser: | |
return Registry.CurrentUser; | |
case RegistryHive.DynData: | |
return Registry.DynData; | |
case RegistryHive.LocalMachine: | |
return Registry.LocalMachine; | |
case RegistryHive.PerformanceData: | |
return Registry.PerformanceData; | |
case RegistryHive.Users: | |
return Registry.Users; | |
} | |
throw new NullReferenceException("Unable to get registry key: " + Hive); | |
} |
Now we must create the methods for getting and setting the values within our class.
These methods will use the previously created function to access the RegistryKey
object we need to access the subkey.
protected T GetValue<T>(string key, T defaultValue) | |
{ | |
try | |
{ | |
using (var rk = GetRegistryKey()) | |
{ | |
using (var sk = rk.OpenSubKey(RootKey)) | |
{ | |
object o = null; | |
if (sk == null || (o = sk.GetValue(key, null)) == null) | |
SetValue(key, (o = defaultValue)); | |
return (T)o; | |
} | |
} | |
} | |
catch (Exception ex) | |
{ | |
Trace.TraceError("Failed to get value for {0}: {1}", key, ex); | |
throw; | |
} | |
} | |
protected void SetValue<T>(string key, T value) | |
{ | |
try | |
{ | |
using (var rk = GetRegistryKey()) | |
{ | |
using (var sk = rk.CreateSubKey(RootKey)) | |
{ | |
sk.SetValue(key, value); | |
} | |
} | |
} | |
catch (Exception ex) | |
{ | |
Trace.TraceError("Failed to set value for {0}: {1}", key, ex); | |
throw; | |
} | |
} |
A handy function we can create from the GetValue
method, is one where we can check if a value exists!
public bool Exists(string key) | |
{ | |
return GetValue<object>(key, null) != null; | |
} |
The whole thing!
Here is what the class should look like.
using Microsoft.Win32; | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Reflection; | |
namespace ns_stebo | |
{ | |
public abstract class RegistryConfig | |
{ | |
public RegistryHive Hive | |
{ | |
get; | |
private set; | |
} | |
public string RootKey | |
{ | |
get; | |
private set; | |
} | |
protected RegistryConfig(RegistryHive hive, string rootKey) | |
{ | |
Hive = hive; | |
RootKey = rootKey; | |
} | |
public bool Exists(string key) | |
{ | |
return GetValue<object>(key, null) != null; | |
} | |
protected T GetValue<T>(string key, T defaultValue) | |
{ | |
try | |
{ | |
using (var rk = GetRegistryKey()) | |
{ | |
using (var sk = rk.CreateSubKey(RootKey)) | |
{ | |
var o = rk.GetValue(key, null); | |
if (o == null) | |
SetValue(key, (o = defaultValue)); | |
return (T)o; | |
} | |
} | |
} | |
catch (Exception ex) | |
{ | |
Trace.TraceError("Failed to get value for {0}: {1}", key, ex); | |
throw; | |
} | |
} | |
protected void SetValue<T>(string key, T value) | |
{ | |
try | |
{ | |
using (var rk = GetRegistryKey()) | |
{ | |
using (var sk = rk.CreateSubKey(RootKey)) | |
{ | |
rk.SetValue(key, value); | |
} | |
} | |
} | |
catch (Exception ex) | |
{ | |
Trace.TraceError("Failed to set value for {0}: {1}", key, ex); | |
throw; | |
} | |
} | |
protected RegistryKey GetRegistryKey() | |
{ | |
switch (Hive) | |
{ | |
case RegistryHive.ClassesRoot: | |
return Registry.ClassesRoot; | |
case RegistryHive.CurrentConfig: | |
return Registry.CurrentConfig; | |
case RegistryHive.CurrentUser: | |
return Registry.CurrentUser; | |
case RegistryHive.DynData: | |
return Registry.DynData; | |
case RegistryHive.LocalMachine: | |
return Registry.LocalMachine; | |
case RegistryHive.PerformanceData: | |
return Registry.PerformanceData; | |
case RegistryHive.Users: | |
return Registry.Users; | |
} | |
throw new NullReferenceException("Unable to get registry key: " + Hive); | |
} | |
} | |
} |