app.config / web.config内の変数


92

app.configまたはweb.configファイルで次のようなことをすることは可能ですか?

<appSettings>
 <add key="MyBaseDir" value="C:\MyBase" />
 <add key="Dir1" value="[MyBaseDir]\Dir1"/>
 <add key="Dir2" value="[MyBaseDir]\Dir2"/>
</appSettings>

次に、コードでDir2にアクセスしたいだけです。

 ConfigurationManager.AppSettings["Dir2"]

これは、アプリケーションを別のサーバーや場所にインストールするときに役立ちますapp.config。変更する必要があるのは、全体で1つのエントリだけです。(私はコードですべての連結を管理できることを知っていますが、私はこのようにそれを好みます)。


私は、設定ファイル内のappSettingsキーで直接使用する変数の定義について話していると思います。
ミカエル・カーペンティア

1
また、XML <!ENTITY>宣言を使用してチェックアウトしましたが、MSがweb.configファイルを処理する方法が原因でサポートされていません。
chilltemp 2009年

あなたの努力をありがとう。私はコードを変更しないことを好みます。コードにはすでに次のステートメントが含まれています:string dir2 = ConfigurationManager.AppSettings ["Dir2"]。value = "[MyBaseDir] \ Dir2"の代わりにvalue = "D:\ blahdir \ Dir2"と表示されるapp.configのみをクリーンアップしたい
DeeStackOverflow 2009年

回答:


7

良い質問。

あるとは思いません。簡単な方法があれば、それは非常によく知られていたと思います。Microsoftは、Visual Studio 2010で、配置とテストのためにさまざまな構成ファイルを配置するためのメカニズムを作成していると思います。

ただし、そうは言ったものの、このConnectionStringsセクションのあなたには、「| DataDirectory |」という一種のプレースホルダーがあることがわかりました。多分あなたはそこで何が働いているのかを見ることができます...

ここにmachine.configそれを示した部分があります:

 <connectionStrings>
    <add
        name="LocalSqlServer"
        connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
        providerName="System.Data.SqlClient"
    />
 </connectionStrings>

それは興味深い情報です。たぶん変数はパイプ記号( "|")を使用してアクセスされますか?うーん..これはうまくいくのだろうか:<add key = "Dir2" value = "| MyBaseDir | \ Dir2" />
DeeStackOverflow 2009年

4
DataDirectory値は、実際にはAppDomainのデータ要素です。AppDomain.CurrentDomain.SetData( "DataDirectory"、dataPath);を使用して値をオーバーライドできます。このような他の変数を定義して「自動拡張」できるかどうかはテストしていません...
Peter Lillevold

22

もう少し複雑ですが、はるかに柔軟な代替策は、構成セクションを表すクラスを作成することです。あなたのapp.config/ web.configファイルでは、これを持つことができます:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <!-- This section must be the first section within the <configuration> node -->
    <configSections>
        <section name="DirectoryInfo" type="MyProjectNamespace.DirectoryInfoConfigSection, MyProjectAssemblyName" />
    </configSections>

    <DirectoryInfo>
        <Directory MyBaseDir="C:\MyBase" Dir1="Dir1" Dir2="Dir2" />
    </DirectoryInfo>
</configuration>

次に、.NETコード(この例ではC#を使用します)で、次のような2つのクラスを作成できます。

using System;
using System.Configuration;

namespace MyProjectNamespace {

    public class DirectoryInfoConfigSection : ConfigurationSection {

        [ConfigurationProperty("Directory")]
        public DirectoryConfigElement Directory {
            get {
                return (DirectoryConfigElement)base["Directory"];
            }
    }

    public class DirectoryConfigElement : ConfigurationElement {

        [ConfigurationProperty("MyBaseDir")]
        public String BaseDirectory {
            get {
                return (String)base["MyBaseDir"];
            }
        }

        [ConfigurationProperty("Dir1")]
        public String Directory1 {
            get {
                return (String)base["Dir1"];
            }
        }

        [ConfigurationProperty("Dir2")]
        public String Directory2 {
            get {
                return (String)base["Dir2"];
            }
        }
        // You can make custom properties to combine your directory names.
        public String Directory1Resolved {
            get {
                return System.IO.Path.Combine(BaseDirectory, Directory1);
            }
        }
    }
}

最後に、プログラムコードでは、次のapp.config方法で新しいクラスを使用して変数にアクセスできます。

DirectoryInfoConfigSection config =
  (DirectoryInfoConfigSection)ConfigurationManager.GetSection("DirectoryInfo");
String dir1Path = config.Directory.Directory1Resolved;  // This value will equal "C:\MyBase\Dir1"

1
ありがとうございましたが、コードを変更せずにこの段階で苦労しているので、これを実行しようとしています。
DeeStackOverflow 2009年

コードの最後の行に小さなエラーがあります(中括弧は数えません): "return System.IO.Path.Combine(MyBaseDir、Dir1);" 代わりに「return System.IO.Path.Combine(BaseDirectory、Dir1);」にする必要があります。そうでない場合、メソッドの名前を「Base Directory」から「MyBaseDir」に変更する必要があります
TheWho

16

私のライブラリExpansiveを使用して達成できます。こちらの nuget でも利用できます

これは、これを主要なユースケースとして設計されました。

中程度の例(AppSettingsをトークン拡張のデフォルトソースとして使用)

app.config:

<configuration>
    <appSettings>
        <add key="Domain" value="mycompany.com"/>
        <add key="ServerName" value="db01.{Domain}"/>
    </appSettings>
    <connectionStrings>
        <add name="Default" connectionString="server={ServerName};uid=uid;pwd=pwd;Initial Catalog=master;" provider="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

展開する文字列に.Expand()拡張メソッドを使用します。

var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
connectionString.Expand() // returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"

または

次のように動的ConfigurationManagerラッパー「Config」を使用します(Expand()への明示的な呼び出しは不要です)。

var serverName = Config.AppSettings.ServerName;
// returns "db01.mycompany.com"

var connectionString = Config.ConnectionStrings.Default;
// returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"

高度な例1(AppSettingsをトークン拡張のデフォルトソースとして使用)

app.config:

<configuration>
    <appSettings>
        <add key="Environment" value="dev"/>
        <add key="Domain" value="mycompany.com"/>
        <add key="UserId" value="uid"/>
        <add key="Password" value="pwd"/>
        <add key="ServerName" value="db01-{Environment}.{Domain}"/>
        <add key="ReportPath" value="\\{ServerName}\SomeFileShare"/>
    </appSettings>
    <connectionStrings>
        <add name="Default" connectionString="server={ServerName};uid={UserId};pwd={Password};Initial Catalog=master;" provider="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

展開する文字列に.Expand()拡張メソッドを使用します。

var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
connectionString.Expand() // returns "server=db01-dev.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"

4
この答えは非常に過小評価されていると思います!!
アフマド

ありがとうAhmad!Expansiveの評価を教えてください。
以前は

これはアプリ設定の実行時の「解決」ですが、反復的なキーと値のペアを持つという私の問題を解決します。これにより、構成のメンテナンスが大幅に削減されました。ここでの絶対的なユートピアは、これをSlowCheetahと連携して動作するビルド時プラグインにすることです。できればもう一度+1します。素晴らしいものだ。
アフマド

ライブラリを使用してこれを実現する方法の簡単な例を教えてください。
ライアンゲイツ

これに遭遇したばかりの誰かにとって、このプロジェクトは2011年以来6年間死んでいます:(
user1003916

4

この質問を見ただけだと思った。

つまり、アプリケーション構成内に変数補間はありません。

2つのオプションがあります

  1. 実行時に独自の変数を代入して変数を置き換えることができます
  2. ビルド時に、ターゲットデプロイメント環境の特定の詳細に合わせてアプリケーション構成をマッサージします。設定の悪夢に対処する際のこれに関するいくつかの詳細

これは正しい投稿です。以前の投稿(同じ質問)では、app.config xmlエントリの例が表示されませんでした。私はあなたのリンクをチェックしました-それはあまりにも多くの作業であり、そこに時間を費やすことを好まないです。
DeeStackOverflow 2009年

3

いくつかのオプションがあります。これは、構成ファイルを処理して変数を正しい値に置き換えるビルド/デプロイ手順で行うことができます。

別のオプションは、これをサポートする独自の構成セクションを定義することです。たとえば、次のxmlを想像してください。

<variableAppSettings>
 <variables>
    <add key="@BaseDir" value="c:\Programs\Widget"/>
 </variables>
 <appSettings>
    <add key="PathToDir" value="@BaseDir\Dir1"/>
 </appSettings>
</variableAppSettings>

次に、実行時に変数の置き換えを処理するカスタム構成オブジェクトを使用してこれを実装します。


投稿にxmlが表示されません(xmlタグを投稿できるように、行を5文字インデントします-前回同じ問題がありました)。また、「カスタム構成オブジェクト」とは何ですか?この段階でコーディングを変更すると、かなり後戻りするので、私はこれを達成するためにゼロコーディングを好みます。
DeeStackOverflow 2009年

カスタム構成には間違いなく[シンプル]コーディングが必要です。しかし、私見それは常にあなたの最良の選択肢です。appSettingsはほとんど使用せず、代わりにすべてのプロジェクトのカスタム構成を作成することを好みます。
ポートマン

3

通常、私は自分のweb.configの各設定にアクセスするためのプロパティを持つ静的クラスを作成します。

public static class ConfigManager 
{
    public static string MyBaseDir
    {
        return ConfigurationManager.AppSettings["MyBaseDir"].toString();
    }

    public static string Dir1
    {
        return MyBaseDir + ConfigurationManager.AppSettings["Dir1"].toString();
    }

}

通常、このクラスで必要な場合は、型変換も行います。それはあなたの設定への入力されたアクセスを持つことを可能にし、設定が変更された場合、あなたはそれらを一箇所でしか編集できません。

通常、このクラスで設定を置き換えることは比較的簡単で、はるかに優れた保守性を提供します。


3

あなたがapp.config説明するそのシナリオのためにあなたの環境変数を使うことができます

<configuration>
  <appSettings>
    <add key="Dir1" value="%MyBaseDir%\Dir1"/>
  </appSettings>
</configuration>

それからあなたは簡単にパスを得ることができます:

var pathFromConfig = ConfigurationManager.AppSettings["Dir1"];
var expandedPath = Environment.ExpandEnvironmentVariables(pathFromConfig);

2

内部<appSettings>では、アプリケーションキーを作成できます。

<add key="KeyName" value="Keyvalue"/>

後で、これらを使用してこれらの値にアクセスできます。

ConfigurationManager.AppSettings["Keyname"]

ConfigurationManagerクラスを使用するには、System.Configurationへの参照を追加し、System.Configurationのusingステートメントを追加する必要があります(VBでのインポート)
cjk

2
表示は正しいですが、質問に対する回答ではありません。
ミカエル・カーペンティア

1

DslConfigをお勧めします。DslConfigを使用すると、グローバル構成の階層構成ファイル、サーバーホストごとの構成、各サーバーホスト上のアプリケーションごとの構成を使用できます(AppSpikeを参照)。
これが複雑である場合は、グローバル
構成変数Variables.varを使用できます。Varibales.varで構成するだけです。

baseDir = "C:\MyBase"
Var["MyBaseDir"] = baseDir
Var["Dir1"] = baseDir + "\Dir1"
Var["Dir2"] = baseDir + "\Dir2"

そして、設定値を取得します

Configuration config = new DslConfig.BooDslConfiguration()
config.GetVariable<string>("MyBaseDir")
config.GetVariable<string>("Dir1")
config.GetVariable<string>("Dir2")

0

変数を宣言して使用して、構成ファイル内でappSettingsキーを定義することはできないと思います。私はいつもあなたのようなコードで連結を管理してきました。


0

私はあなたが望むものと少し苦労していますが、オーバーライドファイルをアプリの設定に追加して、そのオーバーライドファイルを環境ごとに設定することができます。

<appSettings file="..\OverrideSettings.config">

0

多くのアイテムを同様の値で構成する必要がある製品を展開する場合、XMLを読み取り、渡されたパラメーターに基づいて更新する小さなコンソールアプリを使用します。これらは、ユーザーに要求した後にインストーラーによって呼び出されます必要な情報。


0

Matt Hamsmithのソリューションに従うことをお勧めします。実装するのが問題である場合は、これをAppSettingsクラスのバックグラウンドで実装する拡張メソッドを作成してみませんか?

何かのようなもの:

    public static string GetValue(this NameValueCollection settings, string key)
    {

    }

メソッド内では、Linqを使用してDictionaryInfoConfigSectionを検索し、一致するキーを持つ値を返します。ただし、設定ファイルを次のように更新する必要があります。

<appSettings>
  <DirectoryMappings>
    <DirectoryMap key="MyBaseDir" value="C:\MyBase" />
    <DirectoryMap key="Dir1" value="[MyBaseDir]\Dir1"/>
    <DirectoryMap key="Dir2" value="[MyBaseDir]\Dir2"/>
  </DirectoryMappings>
</appSettings>

0

私はこの解決策を思いつきました:

  1. アプリケーションのSettings.settingsで、変数ConfigurationBaseを定義しました(type = string Scope = Applicationを使用)
  2. Settings.settingsのターゲット属性に変数を導入しました。これらの属性はすべてScope = Userに設定する必要がありました
  3. app.xaml.csで、ConfigurationBaseの値を読み取りました
  4. app.xaml.csで、すべての変数をConfigurationBase値に置き換えました。実行時に値を置き換えるには、属性をScopr = Userに設定する必要がありました。

すべての属性を手動で変更する必要があるため、このソリューションに本当に満足していません。新しい属性を追加する場合、app.xaml.csでそれを考慮する必要があります。

App.xaml.csのコードスニペットを次に示します。

string configBase = Settings.Default.ConfigurationBase;
Settings.Default.CommonOutput_Directory = Settings.Default.CommonOutput_Directory.Replace("${ConfigurationBase}", configBase);

更新

改善点を見つけました(これもapp.xaml.csのコードスニペットです)。

string configBase = Settings.Default.ConfigurationBase;

foreach (SettingsProperty settingsProperty in Settings.Default.Properties)
{
    if (!settingsProperty.IsReadOnly && settings.Default[settingsProperty.Name] is string)
    {
        Settings.Default[settingsProperty.Name] = ((string)Settings.Default[settingsProperty.Name]).Replace("${ConfigurationBase}", configBase);
    }
}

これで、Type = stringおよびScope = Userを持つ私の設定のすべての属性に対して置換が機能します。このように私はそれが好きだと思います。

UPDATE2

どうやらScope = Applicationの設定は、プロパティを実行する際には必要ありません。


0

3つの可能なソリューション

私はパーティーに遅れるのを知っています。可変構成設定の問題に対する新しい解決策がないか探していました。私が過去に使用したソリューションに触れるいくつかの回答がありますが、ほとんどは少し複雑に見えます。同じ問題に苦しんでいる人々を助けるために、古いソリューションを見て実装をまとめると思いました。

この例では、コンソールアプリケーションで次のアプリ設定を使用しました。

<appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>

1.環境変数を使用する

autocro autocroの答えはそれに触れたと思います。Visual Studioを閉じずにビルドまたはデバッグするときに十分な実装を行っているだけです。私はこのソリューションをその日に使用しました...

  • MSBuild変数を使用するビルド前イベントを作成する

    警告:簡単に置き換えられない変数を使用するため、プロジェクト名などの変数名を使用してください。

    SETX BaseDir "$(ProjectDir)"

  • 変数をリセットします。次のようなものを使用します:

    スタックオーバーフローでの環境変数の更新

  • コードの設定を使用します。

private void Test_Environment_Variables()
{
    string BaseDir = ConfigurationManager.AppSettings["EnvironmentVariableExample"];
    string ExpandedPath = Environment.ExpandEnvironmentVariables(BaseDir).Replace("\"", ""); //The function addes a " at the end of the variable
    Console.WriteLine($"From within the C# Console Application {ExpandedPath}");
}

2.文字列補間を使用します。

  • string.Format()関数を使用する

`

private void Test_Interpollation()
{
    string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"];
    string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
    string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString());
    Console.WriteLine($"Using old interpollation {ExpandedPath}");
}

`

3.静的クラスを使用して、これは私が主に使用するソリューションです。

  • 実装

`

private void Test_Static_Class()
{
    Console.WriteLine($"Using a static config class {Configuration.BinPath}");
}

`

  • 静的クラス

`

static class Configuration
{
    public static string BinPath
    {
        get
        {
            string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"];
            string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
            return SolutionPath + ConfigPath;
        }
    }
}

`

プロジェクトコード:

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>
</configuration>

Program.cs

using System;
using System.Configuration;
using System.IO;

namespace ConfigInterpollation
{
    class Program
    {
        static void Main(string[] args)
        {
            new Console_Tests().Run_Tests();
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }        
    }

    internal class Console_Tests
    {
        public void Run_Tests()
        {
            Test_Environment_Variables();
            Test_Interpollation();
            Test_Static_Class();
        }
        private void Test_Environment_Variables()
        {
            string ConfigPath = ConfigurationManager.AppSettings["EnvironmentVariableExample"];
            string ExpandedPath = Environment.ExpandEnvironmentVariables(ConfigPath).Replace("\"", "");
            Console.WriteLine($"Using environment variables {ExpandedPath}");
        }

        private void Test_Interpollation()
        {
            string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"];
            string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
            string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString());
            Console.WriteLine($"Using interpollation {ExpandedPath}");
        }

        private void Test_Static_Class()
        {
            Console.WriteLine($"Using a static config class {Configuration.BinPath}");
        }
    }

    static class Configuration
    {
        public static string BinPath
        {
            get
            {
                string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"];
                string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
                return SolutionPath + ConfigPath;
            }
        }
    }
}

ビルド前のイベント:

プロジェクト設定->ビルドイベント

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.