Как указать dictionaryAdapter отслеживать изменения из ConfigurationManager.AppSettings?

Я использую DictionaryAdapter для получения настроек из раздела appSettings моего сайта asp.net. Настройка IoC выполняется один раз, во время запуска и все виды различных интерфейсов с геттерами регистрируются с использованием одного объекта Configuration.AppSettings:

 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))));

Раздел appSettings, размещенный в файле Web.config, работает нормально, но у него есть недостаток, когда я хочу обновить некоторые параметры во время выполнения. Поскольку это файл web.config, все приложение перезапускается. Я хотел бы иметь возможность изменять конфигурацию во время выполнения без перезапуска веб-сайта в качестве побочного эффекта. Поэтому я перешел в отдельный файл:

<appSettings configSource="AppSettings.config">

Теперь изменения отражаются при получении их через ConfigurationManager.AppSettings["key"], но они не отражаются при доступе через динамические интерфейсы из DictionaryAdapter.

Есть ли способ заставить DA следить за изменениями в источнике, а не кэшировать значения?

2 ответа

Решение

Хотя я не нашел точного ответа, я нашел обходной путь. Вместо "привязки" DA напрямую к ConfigurationManager я связываюсь с простым прокси-сервером, обертывающим 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];
    }
}

Затем jus tchange связывается с моим экземпляром прокси:

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

Вышесказанное работает для меня. Хотя я могу изменять настройки своего веб-сайта во время выполнения без перезапуска, изменения значений теперь отражаются через динамически сгенерированные прокси через интерфейсы моих настроек.

DictionaryAdapter по умолчанию не кэширует значения. Вот проходной тест, чтобы доказать это.

    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);
    }

Вы уверены, что сами не кешируете значение в своем коде? Можете ли вы воспроизвести поведение в тесте?

Другие вопросы по тегам