質問

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"]

これは、アプリケーションを別のサーバーや場所にインストールするときに役立ちます。この場合、<=>全体で1つのエントリを変更するだけで済みます。 (コード内のすべての連結を管理できることは知っていますが、この方法を好みます。)

役に立ちましたか?

解決

良い質問です。

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

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

これは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>

他のヒント

もう少し複雑ですが、はるかに柔軟な代替案は、構成セクションを表すクラスを作成することです。 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);
            }
        }
    }
}

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

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

Expansiveライブラリを使用して達成できます: http://nuget.org/List/Packages/Expansive ソースはここから入手できます: https://github.com/anderly/Expansive

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

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

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

  1. 実行時に変数を置換するために独自のロールを作成できます
  2. ビルド時に、アプリケーション構成をターゲット展開環境の特定の仕様に合わせてマッサージします。詳細については、 dealingをご覧ください。 configuration-nightmare

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

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

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

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

通常、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();
    }

}

通常、このクラスで必要な場合は型変換も行います。設定への型指定されたアクセスを許可し、設定が変更された場合、1か所でのみ編集できます。

通常、設定をこのクラスに置き換えることは比較的簡単で、メンテナンス性が大幅に向上します。

説明するシナリオのapp.configで環境変数を使用できます

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

その後、次の方法で簡単にパスを取得できます:

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

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

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

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

ConfigurationManager.AppSettings["Keyname"]

DslConfig をお勧めします。 DslConfigを使用すると、Global Configの階層構成ファイル、サーバーホストごとの構成を使用して、各サーバーホスト上のアプリケーションごとに構成できます(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")

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

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

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

同様の値を持つ多くのアイテムを構成する必要がある製品を展開するために、XMLを読み取り、渡されたパラメーターに基づいて更新する小さなコンソールアプリを使用します。必要な情報のユーザー。

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>

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

  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の設定は不要です。

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

ビルド前イベント:

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top