基础概念
App.config简介
不管是控制台程序,还是窗体应用程序,默认的主工程中都会存在App.config文件。App.Config文件就是一个Xml文件,XML 标记和属性是区分大小写的。当然了你也可以在你的工程中手动添加app.config配置文件。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
无论我是建Windows窗体应用程序,还是控制台应用程序,还是Windows服务默认生成的App.config文件都是长这样的.
App.config的好处
- 消除依赖,减少硬编码,可以更灵活的添加配置信息。
- 无需重新编译,可以动态的添加和修改。
- 简单易用,动态可扩展。
App.config相关资源
App.Config配置
connectionStrings配置
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="MyKey"
connectionString="Data Source=localhost;Initial Catalog=ABC;"
providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
从App.config中读取链接字符串:
string connectionString = ConfigurationManager.ConnectionStrings["MyKey"].ConnectionString;
往App.config中写入链接字符串:
//设置连接字符串
string connectionString=“Data Source=localhost;Initial Catalog=ABC;”;
ConnectionStringSettings setConnStr = newConnectionStringSettings("AccessDB", connectionString,"System.Data.OleDb");
//打开当前应用程序的app.config文件,进行操作
Configuration appConfig =ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//由于没有更新连接字符串的方法,所以这里直接再添加一个连接字符串
appConfig.ConnectionStrings.ConnectionStrings.Add(setConnStr);
appConfig.Save();
// 强制重新载入配置文件的ConnectionStrings配置节
ConfigurationManager.RefreshSection("connectionStrings");
appSettings 配置
主要用于整个程序的配置,以键值对的形式出现。(这块注意xml区分大小写
)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="LogPath" value ="LogPath"/>
<add key="ConfigFile" value ="ConfigFile"/>
</appSettings>
</configuration>
通过key获取对应的value值
string logPath = System.Configuration.ConfigurationSettings.AppSettings["LogPath"];
注意:现在 .Net FrameWork 2.0中已经明确表示此ConfigurationSettings属性已经废弃
,建议改为 ConfigurationManager
或 WebConfigurationManager
。
ConfigurationManager.AppSettings这种方式只读,不可修改。
using System.Configuration;
string logPath = ConfigurationManager.AppSettings["LogPath"];
建议使用如下这种方式进行增删改:
private void AccessAppSettings()
{
//获取Configuration对象
Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//根据Key读取<add>元素的Value
string name = config.AppSettings.Settings["name"].Value;
//写入<add>元素的Value
config.AppSettings.Settings["name"].Value = "fx163";
//增加<add>元素
config.AppSettings.Settings.Add("url", "http://www.fx163.net");
//删除<add>元素
config.AppSettings.Settings.Remove("name");
//一定要记得保存,写不带参数的config.Save()也可以
config.Save(ConfigurationSaveMode.Modified);
//刷新,否则程序读取的还是之前的值(可能已装入内存)
System.Configuration.ConfigurationManager.RefreshSection("appSettings");
}
- 根据并不存在的Key值访问元素,甚至使用remove()方法删除不存在的元素,都不会导致异常,前者会返回null。
- add已经存在的元素也不会导致异常,而是concat了已有的Value和新的Value,用","分隔,例如:“olldvalue,newvalue”。
- 特别注意大小写(XML文件是区分大小写的),例如appSettings配置节。
- 可能有读者会想到,既然app.config是标准XML,当然也可以用操纵一般XML文件的方法来读写。这当然是可以的!只不过我认为这样就失去了VS提供app.config文件的意义了,还不如自己定义一个配置文件方便。
configSections配置
自定义configSections,可以自行定义节元素,扩展了appSettings一个节的功能。如下面示例添加了三类<section>
节点:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="quartz" type="System.Configuration.NameValueSectionHandler"/>
<section name="sampleSection1" type="System.Configuration.SingleTagSectionHandler"/>
<section name="sampleSection2" type="System.Configuration.DictionarySectionHandler"/>
</configSections>
<quartz>
<add key="quartz.scheduler.instanceName" value="ExampleDefaultQuartzScheduler"/>
<add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
<add key="quartz.threadPool.threadCount" value="10"/>
<add key="quartz.threadPool.threadPriority" value="2"/>
<add key="quartz.jobStore.misfireThreshold" value="60000"/>
<add key="quartz.jobStore.type" value="Quartz.Simpl.RAMJobStore, Quartz"/>
<!--******************************Plugin配置*********************************************-->
<add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz" />
<add key="quartz.plugin.xml.fileNames" value="~/quartz_jobs.xml"/>
</quartz>
<sampleSection1 setting1="Value1" setting2="value two" setting3="third value" />
<sampleSection2>
<add key="add" value="id=1"/>
<add key="edit" value="id=2"/>
</sampleSection2>
name属性:指的是自定义配置节的名称,即自定义的这个section的名字。
type属性:指的是自定义配置节的类型,即用于接收这个section中相应字段的类,主要包括:System.Configuration.SingleTagSectionHandler
;System.Configuration.DictionarySectionHandler
;System.Configuration.NameValueSectionHandler
;不同的type不但设置配置节的方式不一样,最后访问配置文件的操作上也有差异。
//访问配置节quartz
NameValueCollection nc=(NameValueCollection)ConfigurationSettings.GetConfig("quartz");
MessageBox.Show(nc.AllKeys[0].ToString()+""+nc["Hello"]);
//访问配置节sampleSection1
IDictionary IDTest1 =(IDictionary)ConfigurationSettings.GetConfig("sampleSection1");
string str = (string)IDTest1["setting1"]+" "+(string)IDTest1["setting2"];
MessageBox.Show(str);//输出
//访问配置节sampleSection1的另一个方法
string[] values1=new string[IDTest1.Count];
IDTest1.Values.CopyTo(values1,0);
MessageBox.Show(values1[0]+""+values1[1]); //输出
//访问配置节sampleSection2
IDictionary IDTest2 =(IDictionary)ConfigurationSettings.GetConfig("sampleSection2");
string[] keys=new string[IDTest2.Keys.Count];
string[] values=new string[IDTest2.Values.Count];
IDTest2.Keys.CopyTo(keys,0);
IDTest2.Values.CopyTo(values,0);
MessageBox.Show(keys[0]+" "+values[0]); //输出
配置节处理程序 | 返回类型 |
---|---|
SingleTagSectionHandler | Systems.Collections.IDictionary |
DictionarySectionHandler | Systems.Collections.IDictionary |
NameValueSectionHandler | Systems.Collections.Specialized.NameValueCollectio |
sectionGroup配置
配置节组是使用<sectionGroup>
元素,将类似的配置节分到同一个组中。配置节组声明部分将创建配置节的包含元素,在<configSections>
元素中声明配置节组,并将属于该组的节置于<sectionGroup>
元素中。下面是一个包含配置节组的配置文件的例子:
例子1:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="TestGroup" >
<section name="Test" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
</configSections>
<TestGroup>
<Test>
<add key="Hello" value="World"/>
</Test>
</TestGroup>
<configuration>
下面是访问这个配置节组的代码,注意Type是System.Configuration.NameValueSectionHandler
,这也限制返回的类型是NameValueCollection
NameValueCollection nc=(NameValueCollection)ConfigurationSettings.GetConfig("TestGroup/Test");
MessageBox.Show(nc.AllKeys[0].ToString()+""+nc["Hello"]);
例子2:
<configuration>
<configSections>
<sectionGroup name="MySectionGroup">
<section name="MyFirstSection" type="System.Configuration.DictionarySectionHandler"/>
<section name="MySecondSection" type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup>
</configSections>
<MySectionGroup>
<MyFirstSection>
<add key="First" value="First Section"/>
</MyFirstSection>
<MySecondSection>
<add key="Second" value="Second Section"/>
</MySecondSection>
</MySectionGroup>
</configuration>
注意我们在section的type中给出了System.Configuration.DictionarySectionHandler
,这也限制了我们在具体的ConfigurationElement中只能使用的形式,使得我们GetSection()方法返回的是一个IDictory对象,我们可以根据Key来取得相应的值
public class SectionConfig
{
public string resultValue;
public SectionConfig()
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
IDictionary dic = ConfigurationManager.GetSection("MySectionGroup/MySecondSection") as IDictionary;
this.resultValue = dic["Second"].ToString();
}
}
自定义扩展(高级用法)
参考博客:一步一步教你玩转.NET Framework的配置文件app.config
操作appSettings(补充)
操作App.config需要添加引用System.Configuration
,并且在程序中using System.Configuration
。
-
添加键为keyName、值为keyValue的项
public void AddItem(string keyName, string keyValue) { //添加配置文件的项,键为keyName,值为keyValue Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); config.AppSettings.Settings.Add(keyName, keyValue); config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection("appSettings"); }
-
判断键为keyName的项是否存在
public bool ExistItem(string keyName) { //判断配置文件中是否存在键为keyName的项 foreach (string key in ConfigurationManager.AppSettings) { if (key == keyName) { //存在 return true; } } return false; }
-
获取键为keyName的项的值
public string GetValueItem(string keyName) { //返回配置文件中键为keyName的项的值 return ConfigurationManager.AppSettings[keyName]; }
-
修改键为keyName的项的值
public void ModifyItem(string keyName, string newKeyValue) { //修改配置文件中键为keyName的项的值 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); config.AppSettings.Settings[keyName].Value = newKeyValue; config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection("appSettings"); }
-
删除键为keyName的项
public void RemoveItem(string keyName) { //删除配置文件键为keyName的项 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); config.AppSettings.Settings.Remove(keyName); config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection("appSettings"); }