文章目录
一、引言
起因是和客户沟通过程中发现有个需求客户也不确定具体是啥样的,因为该需求是个列表项,它可能存在多项,但具体有哪些项前期很难确定。于是,我思考后打算用配置文件,将这些项加到配置文件中,供程序读取,也方便后期直接在配置文件中增删项。
配置文件功能其实很常见,就是为了给程序增加灵活性。尤其是对于C/S架构的程序来说,每次更改程序都要更新客户端,很麻烦。所以对于那些可能需要改变的项(例如,网络配置),可以写到配置文件中。
说到配置文件,格式有许多种,ini、json、xml等等。
这次又是在.NET环境下WPF开发,所以通过微软文档学习一下配置文件的使用。
这里提到的“因为不确定有哪些项而把这些项的设置放到配置文件中”的用法,其实不规范,
因为这是把程序的内容给外部人员修改,还是通过配置文件的方式,如果单独做一个配置程序,
相对会好一些。
实际项目中,我觉得尽量不要这么用。
二、.NET配置文件
1. 准备:配置什么?为什么程序需要配置文件?
.NET Framework为开发人员和管理人员提供了配置文件的方式来对应用程序进行控制和带来灵活性。
配置文件是可以根据需要做更改的XML文件(当然,不是所有的配置文件都是XML格式的)。管理员用它来控制程序可以访问哪些受保护的资源、程序将使用哪些版本的程序集,以及远程的程序和对象位于何处。开发人员可以将配置项放在配置文件中,这样就可以不必在每次配置更改时重新编译应用程序。
托管代码可以使用System.Configuration命名空间中的类来从配置文件中的读取配置,但无法将设置写入文件中。
本节主要描述配置文件的基本语法,并介绍三种类型的配置文件:计算机、应用程序和安全性。
1.1. 配置文件的格式
配置文件主要由元素(Element)组成,元素是设置配置信息的逻辑数据结构。
在配置文件中,可以使用标签(tag,<>一对尖括号就是一个标签)来标记一个元素的起始与结束。
例如,<runtime>元素由 <runtime>子元素</runtime> 组成。
空的元素可以写成 <runtime/> 或 <runtime></runtime> 。
配置文件语法格式就是标签式语言的一般写法。有html基础或者用过WPF的XAML的,应该不陌生,能马上掌握。
与所有XML文件一样,配置文件中的语法是区分大小写的(case-sensitive)。
你可以使用预定义属性(predefined attribute,attribute就是标签元素中的 value = “xx”)来指定配置设置,这些属性是元素的起始标签中的名称/值(name/value)对。以下示例为<codeBase>元素指定了两个属性(version和href),该元素指定运行时可以在何处定位程序集。
<codeBase version="2.0.0.0"
href="http://www.litwareinc.com/myAssembly.dll"/>
🔺1.2. 计算机配置文件(Machine.config)
计算机配置文件(也叫电脑配置文件或机器配置文件),Machine.config ,包含了用于整个计算机的设置项(settings)。
该文件位于 %runtime install path%\Config 目录。Machine.config包含了计算机范围内的程序绑定、内置的远程通道和ASP.NET的配置设置。
我在.NET Core的安装目录下没找到,可能是.NET Framework才有的?不过这不是重点,因为配置通常关注的是App.config。
配置系统(指.NET的这一套与配置文件相关的环境)首先在计算机配置文件中查找<appSettings>元素和开发人员定义的其他配置文件设置项。然后再查找程序配置文件(App.config)。为了使计算机配置文件易于管理,最好将这些设置(settings)放在程序配置文件中。但是,将设置放在计算机配置文件中能使系统更易于维护。例如,如果你有一个客户端和服务器程序都使用的第三方组件,那么将该组件的设置放在一个地方会更容易维护。在这种情况下,电脑配置文件是该设置项放置的合适位置,因为可以避免在两个不同的文件中有相同的设置项。
注意:
使用XCOPY部署程序时不会复制电脑配置文件中的设置项。
⭐1.3. 应用程序配置文件(App.config)
应用程序配置文件包含了程序特有的配置。
它包含CLR读取的设置(如程序集绑定策略、远程对象等)和程序读取的设置。
应用程序配置文件的名称和位置取决于应用程序的主机,它可以是以下之一:
-
1️⃣Executable-hosted app 可执行程序
-
这类程序有两个配置文件:一个是源配置文件,由开发者在开发过程中修改;另一个是随程序发布的输出文件。
在Visual Studio中开发时,将应用程序的源配置文件放在工程目录中,并将其“Copy To Output Directory”属性设置为“Copy always”或“Copy if newer”。默认情况下,配置文件名为“App.config”。
要创建与应用程序一起部署的输出配置文件,Visual Studio将源配置文件复制到编译程序集所在的目录中。该文件被命名为<yourappname>.exe.config。例如,一个名为myApp.exe的应用程序会输出一个名为 myApp.exe.config的输出配置文件。
在某些情况下,Visual Studio可能会修改输出配置文件;
2️⃣ASP.NET-hosted app ASP.NET应用程序
- ; 3️⃣Internet Explorer-hosted app 互联网浏览器程序
- 如果是互联网浏览器程序的配置文件,该文件的位置在<link>标签中用以下语法指定:
<link rel="*ConfigurationFileName*" href="*location">
在该标签中,location是配置文件的URL。
它设置了应用程序的基。
该配置文件必须与应用程序位于同一个网站上。
🔺1.4. 安全配置文件
安全配置文件包含于策略级关联的代码组层次结构和权限集的信息。强烈建议使用代码访问安全策略工具(Code Access Security Policy tool,Caspol.exe)来修改安全策略,以确保策略更改不会破坏安全配置文件。
注意:
.NET Framework 4开始,只有在安全策略被更改时才会出现安全配置文件。
安全配置文件在以下位置:
- 企业策略配置文件:
%runtime-install-path%\Config\Enterprisesec.config - 计算机策略配置文件:
%runtime-install-path%Config\Security.config - 用户策略配置文件:
%USERPROFILE%\Application data\Microsoft\CLR security config\vxx.xx\Security.config
⭐2. 小试牛刀:读取应用程序设置项
本节展示如何在.NET Framework应用程序的App.config文件中添加一个简单的设置项,然后通过代码读取该值。
2.1. 添加App.config文件
通过Visual Studio可以很轻易地往工程中添加一个App.config文件。在创建.NET Framework工程后,右击工程 解决方案浏览器(Solution Explorer)并选择添加(Add) > 新建项(New Item)。选择应用程序配置文件 (Application Configuration File)项,然后添加(Add)。
2.2. 添加设置项
打开App.config并在<configuration>元素中添加以下XML代码,
<appSettings>
<add key="occupation" value="dentist"/>
</appSettings>
2.3. 代码访问设置项
要在代码中访问设置项的值,可以通过AppSettings属性内的索引来获取。AppSetting属性使得从配置文件的<appSettings>元素中获取数据变得很简单。
string occupation = ConfigurationManager.AppSettings["occupation"];
2.4. 配置库
尽管可执行程序使用配置文件很简单,但对类库使用配置文件就有些复杂了。类库可以以与可执行程序相同的方式访问配置设置,但是配置设置必须存在于客户端安程序的App.config文件中。即使你把App.config文件和库的汇编文件一起发布,库代码也不会读取该文件。或者,考虑以下在类库中使用配置设置的方法:
- 获取客户端应用程序中的配置设置,并将它们传递给正在从类库实例化的类。
- 实现一个扩展ConfigurationSection类的自定义段类型。为类库保留一个单独的配置文件,然后从客户端应用程序的配置文件中引用库的配置文件。
3. .NET Framework配置文件架构
在上节简单使用配置文件之后,在进一步应用之前,先来简单了解一下.NET框架配置文件的架构。
3.0. 概述
配置文件是标准的XML文件,可以用来更改应用程序的设置和设置策略。
.NET框架的配置内容由元素组成,可以在配置文件中使用元素来控制程序的行为表现。本节的内容表反映了启动、运行时、网络和其它类型配置的架构层次结构。
什么是配置文件的架构呢?
说一说我的理解,
首先.NET平台下可以开发各种类型的程序(Web、桌面、移动端等等,即使是同一种程序,它也会有许多不同)。
在这些不同类型程序的工程中,用到的配置文件在内容和组织形式上有所不同。
不同工程更适合怎样的配置文件呢?
为了解决这个问题,就需要设计各种配置文件的组织形式,使它们适用于各种工程,并且这种形式是随时间而进化的。
所以配置文件的组织形式或者说构成,我认为就是架构。
那到底架构的表现形式是怎么样的,代码中又是什么具体体现?
看下面例子
3.1. 应用程序设置架构 App Settings schema
该架构包含了自定义应用程序设置项,如文件路径、XML Web服务URL、或应用程序其它的自定义配置信息项。上面的读取配置简单例子就是应用程序设置架构的。该架构涉及的元素很少。
<configuration>
<appSettings> // 该元素可包含<add>,<clear>,<remove>标签来控制程序设置项。并且含有一个可选的file属性。
<add> // 该元素用以添加一个name/value对的设置项到应用程序设置项集合中。含key和value属性。
<clear>
<remove>
3.1.1. <appSettings>元素
该元素包含自定义应用程序设置项。它是由.NET框架预定义的配置节(predefined configuration section)。预定义的配置节就是说该元素是.NET框架预先定义好的,可以直接用的,不需要你自己做定义声明。标签一加就可以用了。
<appSettings>元素存储自定义应用程序配置项信息,例如数据库连接字符串、文件路径、XML Web服务URL或其他自定义配置项信息。在<appSettings>元素中指定的键/值对在代码中使用ConfigurationSettings类访问。
你可以在Web.config和App.config配置文件的<appSettings>元素中使用file属性。该属性指定一个配置文件,该文件提供额外设置项或覆盖<appSettings>元素中指定的设置。file属性可以在源码控制团队开发场景中使用,例如当用户希望覆盖应用程序配置文件中指定的项目设置时。
由file属性指定的文件必须有根节点<appSettings>而不是<configuration>。
代码示例
以下示例展示了一个含设置项的外部应用程序设置文件(custom.config):
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<add key="MyCustomSetting" value="MyCustomSettingValue" />
</appSettings>
以下示例展示了一个应用程序配置文件,它引用了上面的外部配置文件,并添加了一些自己的设置项:
<configuration>
<appSettings file="custom.config">
<add key="ApplicationName" value="MyApplication" />
</appSettings>
</configuration>
此元素可用于应用程序配置文件、计算机配置文件和不在应用程序目录级别的Web.config中。
3.1.2. <add>元素
该元素用于添加一个自定义应用程序设置项(所以一个键值对就是最朴素的设置项)。
<appSettings>
<add key="Key of custom setting" value="Value of custom setting" />
</appSettings>
它有key和value两个属性,且这两个属性都是必须的。
代码示例
以下代码展示了如何为应用程序名添加一个自定义配置项,
<appSettings>
<add key="ApplicationName" value="MyApplication" />
</appSettings>
下面代码展示了在ASP.NET程序中,使用<add>元素定义两个兼容性设置项:
<appSettings>
<add key="AppContext.SetSwitch:Switch.System.Globalization.NoAsyncCurrentCulture" value="true" />
<add key="AppContext.SetSwitch:Switch.System.Uri.DontEnableStrictRFC3986ReservedCharacterSets" value="true" />
</appSettings>
3.1.3. <clear>元素
清除自定义应用程序的设置项。
<appSettings>
<clear />
</appSettings>
3.1.4. <remove>元素
移除自定义应用程序设置项。
<appSettings>
<remove key="Key of custom setting" />
</appSettings>
<clear>和<remove>给我的感觉有点像注释的作用。你哪个元素不用了,就用<remove>注释掉。
这套App Settings 架构是用起来最简单的架构,所以没有太多的约束(这边因果倒置了),比较简单随意。但在有些场景下,组织起来就不那么好。它本身没有一个特别强的框架感,需要你自己去组织。
⭐3.2. 配置文件架构 Configuration file schema
配置文件是标准的XML文件,你可以用它来为程序修改设置项与策略配置。.NET框架配置架构是由元素(elements)组成的,在配置文件中使用元素来控制程序的行为。此部分的内容表反映了启动、运行时、网络和其它配置的架构层次结构。
反映了架构层次结构,就是说介绍时所处层次比较高,而不是具体到某个参数怎么配置的。
配置文件架构涉及到许多元素,这些元素是使用配置文件的基础。
3.2.1. <configuration>元素
这是一个在每个配置文件中都能看到的根元素,CLR和.NET框架程序会使用它。
<configuration>
<!-- Configuration settings -->
</configuration>
⭐⭐⭐3.2.2. <section>元素
该元素包含了一个配置节(configuration section,也可以叫配置段、配置项)的声明。
声明一个配置节本质上是为配置文件定义了一个新元素。新元素包含配置节处理程序(即实现IConfigurationSectionHandler 接口的类)读取的设置。定义的配置节的属性和子元素取决于用于读取设置的节处理程序(section handler)。
⭐⭐:
<section>是配置节,就是在配置文件中的基本配置项。
既然有了配置项,肯定需要在程序中能够读取,所以就需要配置节处理程序。
配置节处理程序有三种SingleTagSectionHandler、NameValueSectionHandler 和DictionarySectionHandler。
从命名上也可以大致看出区别,第一个是读上来看作单个标签的、第二个看作键值对、第三个看作词典。
下面代码示例,就是声明一个单标签类型的配置节,
<configuration>
<configSections>
<section name="sampleSection"
type="System.Configuration.SingleTagSectionHandler"
allowLocation="false" />
</configSections>
<sampleSection setting1="Value1"
setting2="value two"
setting3="third value" />
</configuration>
下面代码展示了如何读取单配置节,
// 虽然说是单配置节,但是它里面还是可以有许多个项的,读上来也是个词典
IDictionary dict1 = (IDictionary)ConfigurationManager.GetSection("sampleSection");
foreach (string key in dict1.Keys)
{
MessageBox.Show(key + ":" + dict1[key]);
}
3.2.2. <configSections>元素
它包含了配置节(configuration section)和命名空间声明。
如果该元素在配置文件中,那它必须是<configuration>的第一个孩子。
<configuration>
<configSections>
<section name="sampleSection"
type="System.Configuration.SingleTagSectionHandler" />
</configSections>
<sampleSection setting1="Value1"
setting2="value two"
setting3="third value" />
</configuration>
3.2.3. <sectionGroup>元素
该元素(也叫配置节组)为配置节定义了一个命名空间。
<sectionGroup name="section group name">
<!-- Configuration sections -->
</sectionGroup>
声明一个配置节组会为配置节创建容器标签,可以确保与其它定义的配置节没有命名上的冲突。<sectionGroup>元素可以彼此嵌套。
<configuration>
<configSections>
<sectionGroup name="mySectionGroup">
<section name="mySection"
type="System.Configuration.NameValueSectionHandler,System" />
</sectionGroup>
</configSections>
<mySectionGroup>
<mySection>
<add key="key1" value="value1" />
</mySection>
</mySectionGroup>
</configuration>
3.2.4. SingleTagSectionHandler的自定义元素
在由section元素定义的自定义配置节中定义设置,并使用SingleTagSectionHandler类。
<sectionName>元素是在<configSections>元素中由<section>标签定义的自定义元素。当调用Configuration.GetSection(String)时,配置系统(configuration system)会返回一个IDictionary对象。
以下示例声明了一个叫<sampleSection>元素,它包含由SingleTagSectionHandler类读取的设置项:
<configuration>
<configSections>
<section name="sampleSection"
type="System.Configuration.SingleTagSectionHandler" />
</configSections>
<sampleSection setting1="Value1"
setting2="value two"
setting3="third value" />
</configuration>
3.2.5. NameValueSectionHandler和DictionarySectionHandler的自定义元素
定义使用NameValueSectionHandler和DictionarySectionHandler类的自定义配置节的设置。
下面例子展示了如何声明一个使用DictionarySectionHandler和NameValueSectionHandler的节。
第一个自定义元素为<dictionarySample>,它包含由System.dll程序集中的DictionarySectionHandler类读取的设置项。
第二个自定义元素是<mySection>,它包含System.dll程序集中的NameValueSectionHandler类读取的设置。
<configuration>
<configSections>
<section name="dictionarySample" type="System.Configuration.DictionarySectionHandler,System" />
<sectionGroup name="mySectionGroup">
<section name="mySection" type="System.Configuration.NameValueSectionHandler,System" />
</sectionGroup>
</configSections>
<dictionarySample>
<add key="myKey" value="myValue" />
</dictionarySample>
<mySectionGroup>
<mySection>
<add key="key1" value="value1" />
</mySection>
</mySectionGroup>
</configuration>
读取示例:
NameValueCollection nvc = (NameValueCollection)ConfigurationManager.GetSection("mySection");
foreach (string key in nvc.AllKeys)
{
MessageBox.Show(key + ":" + nvc[key]);
}
IDictionary dict = (IDictionary)ConfigurationManager.GetSection("dictionarySample");
foreach (string key in dict.Keys)
{
MessageBox.Show(key + ":" + dict[key]);
}
三、结尾
通过本文对.NET框架配置文件几个点大致了解,并能简单应用。
1️⃣ 两种基本架构appSettings架构和配置文件架构
2️⃣ 配置文件中的基本元素
3️⃣ 简单项读写
4️⃣ 集合项读写