app.config / web.config中的variables

是否可以在app.configweb.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一个条目。 (我知道我可以pipe理代码中的所有连接,但我更喜欢这种方式)。

好问题。

我不认为有。 我相信如果有一个简单的方法,这将是相当有名的,我看到微软正在Visual Studio 2010中创build一个机制,用于部署和testing不同的configuration文件。

但是,这样说, 我发现你在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> 

稍微复杂一点,但更为灵活的select是创build一个代表configuration部分的类。 在你的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#),你可以创build两个类:

 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 Dir1 { get { return (String)base["Dir1"]; } } [ConfigurationProperty("Dir2")] public String Dir2 { get { return (String)base["Dir2"]; } } // You can make custom properties to combine your directory names. public String Dir1Resolved { get { return System.IO.Path.Combine(MyBaseDir, Dir1); } } } } 

最后,在你的程序代码中,你可以通过这种方式使用你的新类来访问你的app.configvariables:

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

您可以使用我的Expansive库完成: http : //nuget.org/List/Packages/Expansive源可在这里: https : //github.com/anderly/Expansive

我以为我刚看到这个问题。

总之,不,在应用程序configuration中没有可变插值。

你有两个select

  1. 你可以推出自己的代码来在运行时replacevariables
  2. 在构build时,将应用程序configuration按摩到目标部署环境的特定细节。 在处理configuration噩梦的一些细节

你有几个select。 你可以用一个构build/部署步骤来完成这个工作,它将处理你的configuration文件,用正确的值replace你的variables。

另一个select是定义你自己的支持这个的configuration部分。 例如想象这个XML:

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

现在,您将使用自定义configuration对象来实现这个function,这些对象将在运行时处理replace您的variables。

通常情况下,我最终编写一个静态类的属性来访问我的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(); } } 

通常,我也会在这个类中需要时进行types转换。 它允许对你的configuration进行types化的访问,如果设置改变,你可以在一个地方编辑它们。

通常,用这个类replace设置相对容易,并提供了更好的可维护性。

我会build议你DslConfig 。 使用DslConfig,您可以使用全局configuration,configuration每个服务器主机的层次结构configuration文件来configuration每个服务器主机上的每个应用程序(请参阅AppSpike)。
如果这对你来说很复杂,你可以使用全局configurationVariables.var
只需在Varibales.var中configuration

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

并获取configuration值

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

你可以在你的app.config中使用你描述的场景中的环境variables

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

那么你可以很容易地得到的path:

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

我不认为你可以声明和使用variables来定义configuration文件中的appSettings键。 我总是像你一样pipe理代码连接。

我正在努力与你想要什么,但你可以添加覆盖文件的应用程序设置,然后有覆盖文件设置在每个环境的基础上。

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

对于需要configuration许多具有相似值的项目的产品,我们使用小型控制台应用程序来读取XML,并根据传入的参数进行更新。然后在安装程序询问用户要求(提供)的信息。

我会推荐以下Matt Hamsmith的解决scheme。 如果这是一个需要实现的问题,为什么不创build一个在AppSettings类的后台实现这个扩展方法?

就像是:

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

在方法内部,您使用Linq通过DictionaryInfoConfigSection进行search,并使用匹配键返回值。 你需要更新configuration文件,以下面的内容:

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

<appSettings>里面你可以创build应用程序密钥,

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

稍后,您可以使用以下方式访问这些值:

 ConfigurationManager.AppSettings["Keyname"] 

我想出了这个解决scheme:

  1. 在Settings.settings应用程序中,我定义了一个variablesConfigurationBase(使用type = string Scope = Application)
  2. 我在Settings.settings中的目标属性中引入了一个variables,所有这些属性都必须设置为Scope = User
  3. 在app.xaml.cs中,我读出了ConfigurationBase的值
  4. 在app.xaml.cs中,我用ConfigurationBase值replace了所有的variables。 为了在运行时replace这些值,必须将属性设置为Scopr = User

我对这个解决scheme并不满意,因为我必须手动改变所有的属性,如果我添加一个新的,我必须把它看作是app.xaml.cs.

这里是一个来自App.xaml.cs的代码片段:

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

UPDATE

刚刚发现了一个改进(同样来自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。

三种可能的解决方

我知道我迟到了,我一直在寻找是否有任何新的解决scheme的variablesconfiguration设置问题。 有几个答案可以触及我过去使用的解决scheme,但大多数似乎有些复杂。 我想我会看看我的旧的解决scheme,并把它们放在一起,这样可以帮助那些在同样的问题上挣扎的人们。

对于这个例子,我在控制台应用程序中使用了以下应用程序设置:

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

1.使用环境variables

我相信autocro autocro的答案触及它。 我只是做一个实施,应该足够的时候build设或debugging,而不必closuresVisual Studio。 我在当天使用了这个解决scheme

  • 创build将使用MSBuildvariables的预生成事件

    警告:使用一个不易被replace的variables,所以使用你的项目名称或类似的东西作为variables名称。

    SETX BaseDir "$(ProjectDir)"

  • 重置variables; 使用如下所示:

    刷新堆栈溢出的环境variables

  • 使用您的代码中的设置:

 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插值:

  • 使用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.使用静态类,这是我主要使用的解决scheme。

  • 执行

`

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

预build事件:

项目设置 – >生成事件