Search code examples
.netconfigurationapp-config

Is there a way to override ConfigurationManager.AppSettings?


I really want to be able to have a way to take an app that currently gets its settings using ConfigurationManager.AppSettings["mysettingkey"] to actually have those settings come from a centralized database instead of the app.config file. I can make a custom config section for handling this sort of thing, but I really don't want other developers on my team to have to change their code to use my new DbConfiguration custom section. I just want them to be able to call AppSettings the way they always have but have it be loaded from a central database.

Any ideas?


Solution

  • If you don't mind hacking around the framework and you can reasonably assume the .net framework version the application is running on (i.e. it's a web application or an intranet application) then you could try something like this:

    using System;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Configuration.Internal;
    using System.Reflection;
    
    static class ConfigOverrideTest
    {
      sealed class ConfigProxy:IInternalConfigSystem
      {
        readonly IInternalConfigSystem baseconf;
    
        public ConfigProxy(IInternalConfigSystem baseconf)
        {
          this.baseconf = baseconf;
        }
    
        object appsettings;
        public object GetSection(string configKey)
        {
          if(configKey == "appSettings" && this.appsettings != null) return this.appsettings;
          object o = baseconf.GetSection(configKey);
          if(configKey == "appSettings" && o is NameValueCollection)
          {
            // create a new collection because the underlying collection is read-only
            var cfg = new NameValueCollection((NameValueCollection)o);
            // add or replace your settings
            cfg["test"] = "Hello world";
            o = this.appsettings = cfg;
          }
          return o;
        }
    
        public void RefreshConfig(string sectionName)
        {
          if(sectionName == "appSettings") appsettings = null;
          baseconf.RefreshConfig(sectionName);
        }
    
        public bool SupportsUserConfig
        {
          get { return baseconf.SupportsUserConfig; }
        }
      }
    
      static void Main()
      {
        // initialize the ConfigurationManager
        object o = ConfigurationManager.AppSettings;
        // hack your proxy IInternalConfigSystem into the ConfigurationManager
        FieldInfo s_configSystem = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic);
        s_configSystem.SetValue(null, new ConfigProxy((IInternalConfigSystem)s_configSystem.GetValue(null)));
        // test it
        Console.WriteLine(ConfigurationManager.AppSettings["test"] == "Hello world" ? "Success!" : "Failure!");
      }
    }