2008-10-01 19 views
22

ConfigurationManager.AppSettings ["mysettingkey"]を使用して設定を取得するアプリを実際に取得する方法が本当に必要なのは、これらの設定をapp.configファイルではなく集中データベースから取得することです。この種のことを処理するためのカスタム設定セクションを作成できますが、私のチームの他の開発者が新しいDbConfigurationカスタムセクションを使用するようにコードを変更する必要はありません。 AppSettingsをいつものように呼び出すことができるようにしたいのですが、中央データベースからロードすることができます。ConfigurationManager.AppSettingsをオーバーライドする方法はありますか?

アイデア?

答えて

22

あなたは、フレームワークの周りハッキング気にしないと、あなたは合理的に、あなたはこのような何かを試みることができる(すなわち、それは、Webアプリケーションやイントラネット・アプリケーションの)アプリケーションが実行されている.NET Frameworkのバージョンをとることができる場合は、次の

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フレームワークのバージョンは上記の例とは特に関係がありますか?つまり、私は似たような例を試していますが、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のAddメソッドを試して、アプリケーションの起動時にDB設定を追加することができます。

1

リダイレクトのレイヤーを1つ追加する必要がありますか? ConfigurationManager.AppSettings ["key"]は常に設定ファイルを調べます。あなたはConfigurationFromDatabaseManagerを作ることができますが、これは別の呼び出し構文を使用してになります:

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

私は質問の理由は、すべての既存の使用をオーバーライドする必要があると思います拡張コードベースの変更の必要性を取り除くために、しかし間違っている可能性があります。 –

+1

しかし、これは存在する唯一のクリーンなソリューションです(Azureポータルからアプリ設定を設定できるAzure Webアプリケーションを作成している場合を除く)。 –

-1

のmachine.configののappSettings定義セクションでAllowOverrideの属性を設定することで、.NET 3.5をこの中に行う方法があります表示されます。これにより、独自のapp.configファイル内のセクション全体をオーバーライドし、それを処理する新しいタイプを指定することができます。

+3

これは質問のポイントを逃したと思います。私の質問は、app.configを使用してmachine.configを上書きする方法ではなく、app.configを上書きする方法です。 –

0

私はアプリケーションスターターを作成し、データベースからアプリケーションドメインに設定をロードしようとします。だから、アプリはどのように構成が生成されるかについて何も知らない。 machiene.configを使用すると、dll-hell 2.0に直接つながります。

+0

あなたが話しているこのアプリケーションスターターのことは何ですか? –

0

あなたがあなたを救うことができた場合は、ディスクに設定ファイルを変更 - あなたが別のアプリケーションドメインで代替設定ファイルを読み込むことができます。

AppDomain.CreateDomain("second", null, new AppDomainSetup 
{ 
    ConfigurationFile = options.ConfigPath, 
}).DoCallBack(...); 
関連する問題