Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

KeyConifg - A simple .NET configuration library

0.00/5 (No votes)
19 Jul 2016 1  
Introducing a small library to make configuring your .NET apps just a bit more easier.

Introduction

I'm a fan of strongly typed definitions where ever possible. It is particularly annoying to use the system ConfigurationManager class to extract config settings when you are throwing around strings and parsing values to get your configuration straight. Many times you will find yourself writing code like this.

const string APPSETTING_PORTNUMBER = "PortNumber"; //this is likely to be elsewhere in the app.

int port = int.Parse(ConfigurationManager.AppSettings[APPSETTING_PORTNUMBER]);

Or maybe you don't even bother with the constant, and are guilty of hard-coding those app setting keys right in your code. After my first application that used 50+ of these app settings, I decided to write a library, to make this whole thing a bit easier.

Using the code

With KeyConfig-Net you can create a class that represents your app settings configuration (or other configuration source). KeyConfig-Net is a library comprised of about 200 lines of code, a simple solution to a simple problem. Let's throw up a typical .NET web config configuration file with just the app settings section.

XML
<appSettings>
   <add key="HostName" value="localhost"/>
   <add key="PortNumber" value="45345"/>
</appSettings>

The following code demonstrates a class that will be used to mirror our configuration file.

C#
public class TestConfigClass
{
	[ConfigKey]
	public string HostName { get; set; }

	[ConfigKey]
	public int PortNumber { get; set; }
}

By specifying the TestConfigClass type as the type parameter, Key-Config will use the default parameterless constructor of TestConfigClass to create a new instance of TestConfigClass. It will then scan for the ConfigKey annotations on public and private instance properties (not static). These properties will be assigned with values from the configuration source. The values will be parsed to the proper types as well. The configuration source is an IConfigSource implementation, it defines a source of where to get and save configuration values. Key-Config currently comes with just the AppSettingsSource source but can be extended.

Extracting the configuration from appsettings becomes as simple as this.

C#
var configSettings = ConfigManager<TestConfigClass>.GetConfig(new AppSettingsSource());

//the following passes
Assert.AreEqual("localhost", configSettings.HostName);
Assert.AreEqual(45345, configSettings.PortNumber);

Key-Config can even save app setting values for you.

C#
var source = new AppSettingsSource();
var configSettings = ConfigManager<TestConfigClass>.GetConfig(source);
configSettings.PortNumber = 3423; //changing the port number in appsettings.

ConfigManager<TestConfigClass>.SaveConfig(source, configSettings);

Key-Config annotations also allow you to specify a key value that is different from the property name, as well as indicate if a configuration key is required. In the code below, the Name property will no longer be assigned to the Name configuration key in appsettings, it will instead be looking for IpAddress.

C#
public class TestConfigClass
{
	[ConfigKey(KeyName = "IpAddress", Required = true)]
	public string Name { get; set; }

	[ConfigKey]
	public string Occupation { get; set; }
}

You can check if required values are supplied before grabbing any configuration settings by using the following code. Attempting to access a required field with the GetConfig() method with a required field missing will cause an exception to be thrown.

C#
bool areRequiredFulfilled = ConfigManager<TestConfigClass>.CheckRequired(new AppSettingsSource()); //areRequiredFulfilled indicates if all required fields are not null.

Under The Hood

Key-Config is pretty easy to get an understanding of what is going on under hood.

The solution comprises of the library itself and a very small unit test project. The ConfigManager class contains the meat of the project. It contains static methods to manipulate configuration sources. Configuration sources are defined via implementing the IConfigSource interface. You can use this interface to easily extend Key-Config, for example to use a database for configuration settings. Feel free to contribute extensions to the GitHub repository.

C#
/// <summary>
   /// Conveys a configuration source, of which configuration settings may be derived from.
   /// </summary>
   public interface IConfigSource
   {
       /// <summary>
       /// Indicates whether the source can have configuration settings written to as well as read.
       /// </summary>
       bool CanSet { get; }

       /// <summary>
       /// Indicates whether a specified config key type can be handled as in stored or retrieved as a config value.
       /// </summary>
       /// <param name="objTyp">The type to check.</param>
       /// <returns>True if the type is allowed, false otherwise.</returns>
       bool GetCanHandle(Type objTyp);

       /// <summary>
       /// Sets a value to the configuration source. Is not called ever if the source indicates its read only.
       /// </summary>
       /// <param name="key">The key to the configuration value.</param>
       /// <param name="value">The value that is to be written to the configuration key.</param>
       /// <param name="instanceType">The object type of which configuration values are being mapped to.</param>
       /// <param name="valueType">The value type.</param>
       void SetValue(string key, object value, Type instanceType, Type valueType);

       /// <summary>
       /// Retrieves a value from the configuration source.
       /// </summary>
       /// <param name="key">The key to the configuration value.</param>
       /// <param name="instanceType">The object type of which configuration values are being mapped to.</param>
       /// <param name="valueType">The value type of what is expected to be returned.</param>
       /// <returns>The object retrieved at the specified key, assuming the valueType. Will be null if the value was not found at the specified key.</returns>
       object GetValue(string key, Type instanceType, Type valueType);

   }

The ConfigManager class uses reflection to obtain attribute values from the passed instance type. Reflection is a powerful language feature in C#, it allows you to examine the structure of a type during runtime. The easiest way to enumerate members of a type during runtime is by accessing the members of a Type object in code.

C#
typeof(TestClass)

Accessing the members of the expression above exposes these potential methods.

These methods return enumerations of type data during runtime, you can examine these members and obtain the attributes they possess, as well as even invoke methods and assign fields and properties, all while your program is running. You can learn more about reflection by reading this MSDN article here: https://msdn.microsoft.com/en-us/library/f7ykdhsy(v=vs.110).aspx

Project Links

Provided are links to the GitHub repository, NuGet package, and documentation for the project.

GitHub:

https://github.com/jhimes144/KeyConfig

Documentation:

https://www.docify.net/Doc/Project_KeyConfigNet

Nuget:

https://www.nuget.org/packages/KeyConfig-Net/

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here