2008-10-01 7 views
22

Я действительно хочу, чтобы иметь возможность принять приложение, которое в настоящее время получает свои настройки, используя ConfigurationManager.AppSettings ["mysettingkey"], чтобы на самом деле эти настройки исходили из централизованной базы данных, а не из файла app.config. Я могу создать настраиваемый раздел конфигурации для работы с подобными вещами, но я действительно не хочу, чтобы другим разработчикам моей команды приходилось менять свой код, чтобы использовать мой новый раздел DbConfiguration. Я просто хочу, чтобы они могли вызвать AppSettings так, как они всегда есть, но загружать его из центральной базы данных.Есть ли способ переопределить ConfigurationManager.AppSettings?

Любые идеи?

ответ

22

Если вы не против взлома вокруг базы, и вы можете разумно предположить, рамочный .net версии приложение работает на (т.е. это веб-приложение или приложение интранета), то вы можете попробовать что-то вроде этого:

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!"); 
    } 
} 
+6

частное отражение ... очень непослушный. –

+0

Какая версия каркаса .net имеет отношение к приведенному выше примеру? i.e .... Я пытаюсь использовать аналогичный пример, но, хотя SetValue, похоже, устанавливает значение, попытка получить конфигурационный параметр завершается неудачно - поэтому, в каких случаях вышеуказанный код может не работать? спасибо –

+2

Закрытое поле 's_configSystem' является деталью реализации' ConfigurationManager' и может измениться в будущей версии фрейма или вообще не существовать (например, mono имеет поле с именем [configSystem] (https: // github. com/mono/mono/blob/effa4c07ba850bedbe1ff54b2a5df281c058ebcb/mcs/class/System.Configuration/System.Configuration/ConfigurationManager.cs # L48)). –

0

Я не уверен, что вы можете переопределить его, но вы можете попробовать добавить метод AppSettings, чтобы добавить настройки своего БД при запуске приложений.

1

Что бы вы ни делали, вам нужно будет добавить один слой перенаправления? ConfigurationManager.AppSettings ["key"] всегда будет выглядеть в файле конфигурации. Вы можете сделать ConfigurationFromDatabaseManager, но это приведет, используя другой синтаксис вызова:

ConfigurationFromDatabaseManager.AppSettings["key"] instead of ConfigurationSettings["key"]. 
+2

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

+1

Тем не менее, это единственное чистое решение, которое существует (если вы не создаете веб-приложение Azure, где вы можете установить параметры приложения через портал Azure). –

-1

Оказывается, есть способ сделать это в .NET 3.5 с помощью атрибута AllowOverride в разделе определений AppSettings из machine.config. Это позволяет переопределить весь раздел в вашем собственном файле app.config и указать новый тип для его обработки.

+3

Я думаю, что это пропустило вопрос. Мое чтение вопроса заключается в том, как переопределить app.config, а не как использовать app.config для переопределения machine.config. –

0

Я бы попытался написать стартер приложения и загрузить настройки из базы данных в домен приложения. Таким образом, приложение ничего не знает о том, как создается его конфигурация. Использование machiene.config ведет непосредственно в dll-hell 2.0.

+0

Что это за приложение, которое вы говорите? –

0

Если вы можете сохранить вас измененный конфигурационный файл на диск - вы можете загрузить альтернативный конфигурационный файл в другом домене приложения:

AppDomain.CreateDomain("second", null, new AppDomainSetup 
{ 
    ConfigurationFile = options.ConfigPath, 
}).DoCallBack(...); 

 Смежные вопросы

  • Нет связанных вопросов^_^