1

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?

Łukasz Podolak
  • 958
  • 3
  • 12
  • 24

2 Answers2

1

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.

Łukasz Podolak
  • 958
  • 3
  • 12
  • 24
0

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?

Krzysztof Kozmic
  • 27,267
  • 12
  • 73
  • 115
  • Indeed this prooves to work. If you bind to ConfigurationManager.AppSettings instead in the same test, it will work as well. However, the point is that changes are not being reflected if you operate in website context and change values in appsettings.config file, instead of via code (as shown in example). I'm not sure where the problem lies exactly, whether is it DA or CM. I'm having troubles to reproduce my scenario in unit test, as this would involve changing config file (not collection via code) and having web context as well. – Łukasz Podolak Jun 21 '13 at 13:45
  • Anyway, I found a simple workaround to my problem that does the job very well, so I'll leave it as is. Anyway, thanks a lot, as your post helped to solve my problem. – Łukasz Podolak Jun 21 '13 at 13:47