app.config/web.config 中的变量
Posted
技术标签:
【中文标题】app.config/web.config 中的变量【英文标题】:Variables within app.config/web.config 【发布时间】:2010-10-10 19:42:34 【问题描述】:是否可以在 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
中的一个条目。
(我知道我可以管理代码中的所有串联,但我更喜欢这种方式)。
【问题讨论】:
我认为他是在谈论直接在配置文件中定义要在 appSettings 键中使用的变量。 我也使用 XML 声明进行了检查,但由于 MS 处理 web.config 文件的方式,它不受支持。 感谢您的努力。我不想修改任何代码。代码已经有一条语句:string dir2=ConfigurationManager.AppSettings["Dir2"]。我只想清理 app.config 现在说 value="D:\blahdir\Dir2" 而不是 value="[MyBaseDir]\Dir2" 【参考方案1】:您可以使用我的库Expansive 来完成。也可以在 nuget here 上找到。
它是以此为主要用例设计的。
中等示例(使用 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;"
或
如下使用 Dynamic 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;"
【讨论】:
我认为这个答案被低估了!! 谢谢艾哈迈德!让我知道您对 Expansive 的喜爱程度。 虽然这是应用程序设置的运行时“解决方案”,但它解决了我存在重复键值对的问题。我们使用它显着减少了配置维护。这里绝对的乌托邦是让它成为一个与 SlowCheetah 一起工作的构建时间插件。如果可以的话,我会再次 +1。好东西安德利。 您能否提供一个简短的示例,说明如何使用您的库来完成此任务? 对于其他刚刚偶然发现此问题的人来说,该项目自 2011 年以来已经死了 6 年 :(【参考方案2】:一个稍微复杂但更灵活的替代方法是创建一个表示配置部分的类。在你的 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#),您可以像这样创建两个类:
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"
【讨论】:
谢谢,但我试图在不修改任何代码的情况下做到这一点,因为在这个阶段很痛苦。 最后一行代码有一个小错误(不包括大括号):“return System.IO.Path.Combine(MyBaseDir, Dir1);”应该改为“return System.IO.Path.Combine(BaseDirectory , Dir1);”,否则该方法应该从 'Base Directory' 重命名为 'MyBaseDir'【参考方案3】:三种可能的解决方案
我知道我迟到了,我一直在寻找是否有任何新的解决方案可以解决可变配置设置问题。有一些答案涉及我过去使用的解决方案,但大多数似乎有点令人费解。我想我会看看我的旧解决方案并将实现放在一起,以便它可以帮助那些正在努力解决同样问题的人。
对于本示例,我在控制台应用程序中使用了以下应用设置:
<appSettings>
<add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
<add key="StaticClassExample" value="bin"/>
<add key="InterpollationExample" value="0bin"/>
</appSettings>
1。使用环境变量
我相信 autocro autocro's answer 触及了它。我只是在做一个在构建或调试时应该足够的实现,而不必关闭 Visual Studio。我以前用过这个解决方案...
创建将使用 MSBuild 变量的预构建事件
警告:使用不容易替换的变量,因此请使用您的项目名称或类似的变量名称。
SETX BaseDir "$(ProjectDir)"
重置变量;使用类似以下内容:
Refresh Environment Variables on Stack Overflow
使用代码中的设置:
'
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="0bin"/>
</appSettings>
</configuration>
程序.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;
预构建事件:
Project Settings -> Build Events
【讨论】:
【参考方案4】:您可以在 app.config
中为您描述的场景使用环境变量
<configuration>
<appSettings>
<add key="Dir1" value="%MyBaseDir%\Dir1"/>
</appSettings>
</configuration>
然后你可以很容易地得到路径:
var pathFromConfig = ConfigurationManager.AppSettings["Dir1"];
var expandedPath = Environment.ExpandEnvironmentVariables(pathFromConfig);
【讨论】:
【参考方案5】:我想出了这个解决方案:
-
在应用程序 Settings.settings 中,我定义了一个变量 ConfigurationBase(type=string Scope=Application)
我在 Settings.settings 的目标属性中引入了一个变量,所有这些属性都必须设置为 Scope=User
在 app.xaml.cs 中,我读出了 ConfigurationBase 中的值
在 app.xaml.cs 中,我用 ConfigurationBase 值替换了所有变量。为了在运行时替换值,必须将属性设置为 Scopr=User
我对这个解决方案不太满意,因为我必须手动更改所有属性,如果我添加一个新属性,我必须在 app.xaml.cs 中考虑它。
这里是来自 App.xaml.cs 的代码 sn-p:
string configBase = Settings.Default.ConfigurationBase;
Settings.Default.CommonOutput_Directory = Settings.Default.CommonOutput_Directory.Replace("$ConfigurationBase", configBase);
更新
刚刚发现一个改进(又是来自 app.xaml.cs 的代码 sn-p):
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 的所有属性。我想我喜欢这样。
更新2
在属性上运行时显然不需要设置 Scope=Application。
【讨论】:
【参考方案6】:我建议你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")
【讨论】:
【参考方案7】:我以为我刚看到这个问题。
简而言之,不,应用程序配置中没有变量插值。
你有两个选择
-
您可以自行滚动以在运行时替换变量
在构建时,根据目标部署环境的特定细节调整应用程序配置。关于这方面的一些细节dealing with the configuration-nightmare
【讨论】:
这是正确的帖子。我之前的帖子(同样的问题)没有显示 app.config xml 条目示例。我检查了你的链接 - 工作量太大,不想花时间在那里。我们有不同的盒子单独的 app.configs,我想摆脱它。【参考方案8】:在<appSettings>
内可以创建应用密钥,
<add key="KeyName" value="Keyvalue"/>
稍后您可以使用以下方法访问这些值:
ConfigurationManager.AppSettings["Keyname"]
【讨论】:
要使用 ConfigurationManager 类,您需要添加对 System.Configuration 的引用并为 System.Configuration 添加 using 语句(在 VB 中导入) 指示是正确的,但不是对所提问题的回答。【参考方案9】:好问题。
我认为没有。我相信如果有一种简单的方法会很出名,而且我看到 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>
【讨论】:
这是有趣的信息。也许使用管道符号(“|”)访问变量?嗯..我想知道这是否可行: DataDirectory 值实际上是 AppDomain 中的一个数据元素。您可以使用 AppDomain.CurrentDomain.SetData("DataDirectory", dataPath); 覆盖该值我还没有测试过你是否可以像这样定义其他变量并让它们“自动扩展”......【参考方案10】:我建议遵循 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>
【讨论】:
【参考方案11】:通常,我最终会编写一个带有属性的静态类来访问我的 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();
通常,我也会在此类需要时进行类型转换。它允许对您的配置进行键入访问,如果设置发生更改,您只能在一个地方进行编辑。
通常,用此类替换设置相对容易,并且可提供更好的可维护性。
【讨论】:
【参考方案12】:为了推出需要配置大量具有相似值的项目的产品,我们使用小型控制台应用程序读取 XML 并根据传入的参数进行更新。然后安装程序在询问用户获取所需信息。
【讨论】:
【参考方案13】:您有几个选择。您可以通过构建/部署步骤来执行此操作,该步骤将处理您的配置文件,用正确的值替换您的变量。
另一种选择是定义您自己的支持此配置的部分。例如想象这个 xml:
<variableAppSettings>
<variables>
<add key="@BaseDir" value="c:\Programs\Widget"/>
</variables>
<appSettings>
<add key="PathToDir" value="@BaseDir\Dir1"/>
</appSettings>
</variableAppSettings>
现在您将使用自定义配置对象来实现这一点,该对象将在运行时为您替换变量。
【讨论】:
我在帖子中没有看到你的 xml(缩进你的第 5 行字符以便能够发布 xml 标签 - 我上次遇到了同样的问题)。另外,什么是“自定义配置对象”?我更喜欢零编码来实现这一点,因为在这个阶段改变编码会让我们倒退很多。 自定义配置肯定涉及[简单]编码。但恕我直言,它始终是您的最佳选择。我几乎从不使用 appSettings,而是更喜欢为每个项目创建自定义配置。【参考方案14】:我正在为您想要的东西而苦苦挣扎,但您可以将覆盖文件添加到应用程序设置中,然后根据每个环境设置该覆盖文件。
<appSettings file="..\OverrideSettings.config">
【讨论】:
【参考方案15】:我认为您不能在配置文件中声明和使用变量来定义 appSettings 键。我一直像你一样在代码中管理串联。
【讨论】:
以上是关于app.config/web.config 中的变量的主要内容,如果未能解决你的问题,请参考以下文章
从 App.Config 将程序集加载到 AppDomain
如何在visual studio解决方案中查看app.config或web.config中对键的所有引用/调用?