Question

I use DictionaryAdapter to retrieve settings from appSettings section of my asp.net website. The IoC configuration is done once, at the startup time and all kinds of different interfaces with getters are being registered with using single Configuration.AppSettings object:

 var dictionaryAdapterFactory = new DictionaryAdapterFactory();
        container.Register(
            Types
                .FromAssemblyNamed(assemblyName)
                .Where(t => t.Name.EndsWith("AppSettings"))
                .Configure(
                    component => component.UsingFactoryMethod(
                        (kernel, model, creationContext) =>
                        dictionaryAdapterFactory.GetAdapter(creationContext.RequestedType, ConfigurationManager.AppSettings))));

The appSettings section hosted in Web.config file works fine, but it has its drawback when I want to update some settings during runtime. As it is web.config file, the whole app is restarted. I would like to be able to modify configuration at runtime without restarting website as a side effect. Therefore, I moved into separate file:

<appSettings configSource="AppSettings.config">

Now, changes are being reflected when retrieving them via ConfigurationManager.AppSettings["key"], but they are not reflected when accessing via dynamic interfaces from DictionaryAdapter.

Is there any way to have tell DA to watch for the changes in source and not cache the values?

Was it helpful?

Solution

Although I didn't find the exact answer, I found a workaround. Instead of 'binding' DA directly to ConfigurationManager, i bind to a simple proxy that wraps CM:

public class AppSettingsProxy : NameValueCollection
{
    public override string Get(string name)
    {
        return ConfigurationManager.AppSettings[name];
    }

    public override string GetKey(int index)
    {
        return ConfigurationManager.AppSettings[index];
    }
}

Then jus tchange binding to my proxy instance:

  container.Register(
            Types
                .FromAssemblyNamed(assemblyName)
                .Where(t => t.Name.EndsWith("AppSettings"))
                .Configure(
                    component => component.UsingFactoryMethod(
                        (kernel, model, creationContext) =>
                        dictionaryAdapterFactory.GetAdapter(creationContext.RequestedType, appSettingsProxy))));

The above works for me. While I can modify my website's settings at runtime without an restart, value changes now are reflected via dynamically generated proxes over my settings interfaces.

OTHER TIPS

DictionaryAdapter does not itself by default cache the values. Here's a passing test to prove that.

    public interface IFoo
    {
        string Foo { get; set; } 
    }

    [Test]
    public void Adapter_does_not_cache_values_once_read()
    {
        var dict = new NameValueCollection { { "Foo", "Bar" } };

        var adapter = (IFoo)factory.GetAdapter(typeof(IFoo), dict);

        var value = adapter.Foo;

        dict["Foo"] = "Baz";
        var value2 = adapter.Foo;

        Assert.AreNotEqual(value, value2);
        Assert.AreEqual("Baz", value2);
    }

Are you sure you're not caching the value yourself in your code? Can you reproduce the behaviour in a test?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top