AppSettings and Xml config seem to be the staple for ASP.NET developers, but in production they aren’t good for configuration that needs to change on the fly. Modifications to the web.config cause a worker process recycle, and if you use config files external to the web config, modifying them wont cause a recycle, but you need to force a recycle to pick up the changes.
If you are using something like configinjector, and startup validation of your settings this might be not a bad thing, however if you have costly start-up times for your app for pre-warming cache etc, this maybe less than desirable.
Recently we’ve been using consul to manage our configuration, for both service discovery and K/V store (replacing a lot of our app settings).
So we’ve started to use a pattern in some of our libraries to manage their settings from code as opposed to filling our web config with hordes of xml data.
The way this works is we store our config in a singleton that is configured at app startup programatically. This allow us to load in value from what ever source we want, and abstracts the app settings as a dependency. Then if at run time you need to update the settings you can call the same method.
Then to make things nice and fluent we add extension methods to add the configuration to the class then update the singleton with a Create method at the end.
public class Configurator { public static Configurator Current => _current ?? (_current = new Configurator()); private static object _locker = new object(); private static Configurator _current; public static Configurator RegisterConfigurationSettings() { return new Configurator(); } internal bool MySetting1 = true; internal int MySetting2 = 0; public void Create() { lock (_locker) { _current = this; } } } public static class ConfiguratorExt { public static Configurator DisableMySetting1(this Configurator that) { that.MySetting1 = false; return that; } public static Configurator WithMySetting2Of(this Configurator that, int myVal) { that.MySetting2 = myVal; return that; } }
You could also implement what i have done as extension method into the configurator class, but i tend to find when the class gets big it helps to break it up a bit.
This allows us to programtically configure the library at run time, and pull in the values from where ever we like. for example below
void PopulateFromAppSettings() { Configurator.RegisterConfigurationSettings() .WithMySetting2Of(ConfigurationManager.AppSettings["MySetting2"]) .Create(); } void PopulateFromConsul() { var MySetting2 = // Get value from Consul Configurator.RegisterConfigurationSettings() .WithMySetting2Of(MySetting2) .Create(); }
You’ll also notice the locker object that we use to make the operation thread safe.
After populating the object we can use the read only Configurator.Current singleton form anywhere in or app to access the configuration settings.