DotText源码学习——从配置文件Web.config入手(一)

2010-03-19 17:18 by 吴秦, 2409 阅读, 12 评论, 收藏, 编辑

概述

ASP.NET配置数据存储在名为Machine.config/Web.config的XML文本文件中,Web.config文件可以出现在ASP.NET应用程序的多个目录中。由于这些文件将应用程序配置设置与应用程序代码分开,可以方便地设置与应用程序关联。正是因为配置文件中存储着关于整个应用程序的设置,当我读一个陌生项目的源码时,经常把它作为入口。

我将从以下几点分析ASP.NET配置文件:

  1. ASP.NET配置文件的层次结构
  2. Machine.config和根Web.config配置文件
  3. ASP.NET配置文件的结构
  4. 自定义配置节及配置节处理程序
  5. 访问配置文件中的配置数据

1、ASP.NET配置文件的层次结构

ASP.NET配置文件完全是基于XML的,它们可以出现在ASP.NET应用程序的多个目录中。ASP.NET配置层次结构具有以下特征:

  • 使用应用于配置文件所在的目录及其所有子目录中的资源的配置文件。
  • 允许将配置数据放在将使它具有适当范围(整台计算机、所有的Web应用程序、单个应用程序或该应用程序中的子目录)的位置。
  • 允许重写从配置层次中的较高级别继承的配置设置。还允许锁定配置设置,以防止他们被较低级别的配置设置所重写。
  • 将配置设置的逻辑组组织成节的形式。

所有的ASP.NET应用程序都从一个名为systemroot\Microsoft .NET\Framework\versionNumber\CONFIG\Machine.conf的文件继承基本设置和默认值。Machine.config文件用于服务器级的配置设置。其中某些设置不能再位于层级结构中较低的配置中被重写。ASP.NET配置层次结构的根是一个称为Web.config文件的文件,它与Machine.config文件位于同一个目录中。根Web.config文件继承Machine.config文件中的所有配置,它包括应用于所有运行某一个具体版本的.NET Framework的ASP.NET应用程序的设置。由于每个ASP.NET应用程序都从根Web.config文件那里继承默认配置,因此只需为重写默认配置的设置创建Web.config文件。配置文件层次结构的层次关系如图1所示:

DotText源码学习——从配置文件Web.config入手(一)

2、Machine.config和根Web.config配置文件

Machine.config 文件包含服务器上所有Web 应用程序的ASP.NET 架构,如appSettings、connectionStrings、system.data、xmlSerializer等等配置节都是在machine.config文件中声明的。有兴趣的可以打开machine.config文件研究研究。

processModel 元素(ASP.NET 设置架构)元素配置用于服务器(包括服务器上的所有 ASP.NET 应用程序)的处理模型。因此,processModel 设置只能放在 Machine.config 文件中,而且不能被任何 Web.config 文件中的设置重写。

对 processModel 元素的更改将只有在辅助进程重新启动之后才生效,而不是像其他配置元素那样在设置更改之后立即生效。

当ASP.NET 以辅助进程隔离模式运行在Internet 信息服务 (IIS) 6.0 中时,将使用IIS 6.0 进程模型,并将忽略 Machine.config 文件的processModel 节中的设置。若要配置进程标识、循环或其他进程模型值,要使用IIS 管理器来配置应用程序的IIS 辅助进程。将IIS 6.0 配置为在IIS 5.0隔离模式中运行 ASP.NET 后,就不会运行ASP.NET 2.0。

根Web.config 文件与Machine.config 文件存储在同一个目录中,它包含大部分system.web 配置节的默认值。在这也不一一列举了,请自行查看根web.config文件和msdn。

3、ASP.NET配置文件的结构

所有的ASP.NET配置信息都驻留在.config(Machine.config、Web.config等等,本文以后都用Web.config代指所有配置文件)文件中的configuration元素中。此元素中的配置信息分为两个主区域:配置节处理程序声明区域和配置节设置区域。

注:配置文件中的标记格式是区分大小的,因为这些标记必须是格式良好的 XML,所以标记、子标记和属性是区分大小写的。标记名和属性名是Camel 大小写形式的,这意味着标记名的第一个字符是小写的,后面的任何连接单词的第一个字母是大写的。大多数情况下,字符串属性值是Pascal大小写形式的,这意味着第一个字符是大写的,后面的任何连接单词的第一个字母也是大写的。truefalse例外,它们总是小写的。

3.1、配置节处理程序声明

配置节处理程序声明区域驻留在Web.config文件中的configSections元素内。它包含在其中声明节处理程序的ASP.NET配置section元素。可以将这些配置节处理程序声明嵌套在sectionGroup元素中,以帮助组织配置信息。通常,sectionGroup元素表示要应用配置设置的命名空间。例如,DotText中的配置节声明区域configSections的设置如下面的代码所示。

配置节处理程序声明区域——configSections<configSections>
     <section name="webfx.config" type="CchenSoft.Framework.Config.ConfigurationHandler, CchenSoft.Framework"/>
     <section name="BlogConfigurationSettings" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework"/>
     <section name="HandlerConfiguration" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework"/>
</configSections>

从上述代码可以看出,DotText在web.config配置文件的配置节处理程序声明区域中声明了三个自定义配置节,分别为:

  • webfx.config
  • BlogConfigurationSettings
  • HandlerConfiguration。
<section> 只用到了name和type两种属性.name指定了配置节的名称,而type属性则规定了指定从配置文件中读取节的配置节处理程序类的名称,有两部分,前面为处理程序的类名,后面的为Assembly名称(Assembly必须位于bin目录中)以及版本号,公匙等信息。
配置节设置区域中的每个配置节都有一个节处理程序声明。节处理程序是用来实现ConfigurationSection接口的.NET Framework类(注意:这是.NET2.0的方式,而.NET1.0、1.1节处理程序是用来实现IConfigurationSectionHandler接口的类,DotText比较早使用.NET1.1的方式)。节处理程序声明中包含配置设置节的名称以及用来处理该节中配置数据的节处理程序类的名称,即<section>。如上例中的BlogConfigurationSettings配置节处理程序类为:Dottext.Framework.Util.XmlSerializerSectionHandler,他所在的程序集为:Dottext.Framework(我们可以在bin目录下找到相应的dll)。

只需要声明配置节处理程序一次。默认ASP.NET配置节的节处理程序已在默认的Machine.config文件中进行声明。根Web.config文件和ASP.NET应用程序中的其他配置文件都自动继承在Machine.config文件中声明的配置处理程序。只有当创建用来处理自定义设置节的自定义节处理程序类时,才需要声明新的节处理程序。DotText中就定义了自定义的节处理程序,上例中的Dottext.Framework.Util.XmlSerializerSectionHandler就是。关于如何创建自定义配置节及配置节处理程序本文后面将详细介绍。

3.2、配置节设置

配置节设置区域位于配置节处理程序声明区域之后,它包含实际的配置设置。默认情况下,在内部或者在某个根配置文件中,对于configSections区域中的每一个section和sectionGroup元素,都会有一个指定的配置节元素。配置节元素还可以包含子元素,这些子元素与其父元素由同一个节处理程序处理。如上面DotText例子中的BlogConfigurationSettings配置节在配置节设置区域中的设置如下所示:

配置节设置区域中BlogConfigurationSettings的设置<BlogConfigurationSettings type="Dottext.Framework.Configuration.BlogConfigurationSettings, Dottext.Framework">
	<Tracking enableAggBugs="true" enableWebStats="true" queueStats="false" queueStatsCount="3" enableTrackBacks="false" enablePingBacks="false" pingWeblogs="false"/>
	<EntryHandlers>
		<EntryHandler type="Dottext.Framework.EntryHandling.CommentFormatHandler, Dottext.Framework" postType="Comment" processAction="Insert" processState="PreCommit" isAsync="false"/>
		<EntryHandler type="Dottext.Framework.EntryHandling.CommentDeliveryHandler, Dottext.Framework" postType="Comment" processAction="Insert" processState="PostCommit" isAsync="true"/>
		<EntryHandler type="Dottext.Framework.EntryHandling.EntryValidationHandler, Dottext.Framework" postType="BlogPost Article" processAction="Insert Update" processState="PreCommit" isAsync="false"/>
		<!--<EntryHandler type="Dottext.Framework.EntryHandling.WeblogsPingHandler, Dottext.Framework" postType = "BlogPost" processAction ="Insert Update" processState="PostCommit" isAsync="true" />-->
		<EntryHandler type="Dottext.Framework.EntryHandling.TrackBackHandler, Dottext.Framework" postType="BlogPost Article" processAction="Insert Update" processState="PostCommit" isAsync="false"/>
		<EntryHandler type="Dottext.Framework.EntryHandling.KeyWordHandler, Dottext.Framework" postType="BlogPost Article" processAction="Insert Update" processState="PreCommit" isAsync="false"/>
		<!--<EntryHandler type="Dottext.Framework.EntryHandling.WebServicePostHandler, Dottext.Framework" postType = "BlogPost Article" processAction ="Insert" processState="PreCommit" isAsync="false" />-->
	</EntryHandlers>
	<!-- 
		An event is a configuration for a Dottext.Framework.ScheduledEvents.IEvent. The type property must specify a class which implements
		IEvent. You must also specify a unqiue key for each event and either a mintues interval value or timeOfDay value (both int). Interval is how often
		the event should occur. timeOfDay is the absolute time in minutes. 0 = 12:00 am, 720 = noon, 785 = 1:06 pm.
		
		The first "walk through" will happen 1 minute after an application restart, and then every five minutes.
	-->
	<Events>
		<!-- <Event type="Dottext.Search.SearchEngineSchedule, Dottext.Search" minutes="1" key="SearchEngine"/> -->
		<Event type="Dottext.Framework.Tracking.StatsQueueSchedule, Dottext.Framework" minutes="5" key="StatsQueue"/>
	</Events>
	<EnableMultiHost>false</EnableMultiHost>
	<!-- Checkout DottextHelper for hashing passwords -->
	<UseHashedPasswords>true</UseHashedPasswords>
	<!-- Globally control access to web services -->
	<AllowServiceAccess>true</AllowServiceAccess>
	<AllowImages>true</AllowImages>
	<!-- Globally control use of XHTML -->
	<UseXHTML>false</UseXHTML>
	<ItemCount>25</ItemCount>
	<!-- Server Time Zone -->
	<ServerTimeZone>+8</ServerTimeZone>
	<!-- 网站分类选择方式:true-单选 false-多选 -->
	<GlobalCategorySingleSelect>true</GlobalCategorySingleSelect>
	<!-- 分类级别(1或2) -->
	<CategoryDepth>1</CategoryDepth>
	<!-- Url的扩展名 -->
	<UrlFormat>aspx</UrlFormat>
	<!-- 是否允许所有用户上传文件 -->
	<EnableAllUserUpload>true</EnableAllUserUpload>
	<!-- 站点Logo图片 -->
	<Logo></Logo>
	<!-- 登录是否使用验证码 -->
	<EnableLoginAuhenCode>false</EnableLoginAuhenCode>
	<!-- 匿句用户发表评论是否使用验证码 -->
	<EnableFeedBackAuhenCode>false</EnableFeedBackAuhenCode>
</BlogConfigurationSettings>

从上述代码可以看出,在配置节设置区域配置了一个BlogConfigurationSettings元素,他的相应类为:Dottext.Framework.Configuration.BlogConfigurationSettings。BlogConfigurationSettings元素中又包含许多子元素,如Tracking、EntryHandlers、Events、EnableMultiHost等等,而且他们其中有的还嵌有子元素。这些子元素是Dottext.Framework.Configuration.BlogConfigurationSettings中的一些属性,我们在配置文件中设置这些元素即是设置类中相应属性的值,web.config就相当于一个存储介质。这里一些配置细节看不懂也没关系,只要明白怎么设置配置节,BlogConfigurationSettings以后将会更详细的介绍。

4、自定义配置节及配置节处理程序

要自定义配置节必须要创建相应的配置节处理程序,该处理程序是实现了System.Configuration.ConfigurationSection类的.NET Framework类(.NET2.0的方式,.NET1.x是System.Configuration.IConfigurationSectionHandler)。节处理程序解释并处理Web.config文件特定部分中XML配置元素中定义的设置,并根据配置设置返回适当的配置对象。处理程序类返回的配置对象可以是任何数据结构;它不限于任何基配置类或配置格式。ASP.NET使用该配置对象,以对自定义配置元素进行读取和写入。

下面代码显示了DotText中BlogConfigurationSettings节的处理程序:

配置节BlogConfigurationSettings的处理程序类using System;
using System.Configuration;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;

namespace Dottext.Framework.Util
{
	public class XmlSerializerSectionHandler : IConfigurationSectionHandler 
	{
		public object Create(object parent, object configContext, System.Xml.XmlNode section) 
		{
			XPathNavigator nav = section.CreateNavigator();
			string typename = (string) nav.Evaluate("string(@type)");
			Type t = Type.GetType(typename);
			XmlSerializer ser = new XmlSerializer(t);
			return ser.Deserialize(new XmlNodeReader(section));
		}
	}
}

DotText中是以.NET1.X的方式,我们完全可以把它用.NET2.0的方式改写。跟.NET1.X相比从 System.Configuration.ConfigurationSection 类继承允许对节处理程序进行更精细的控制。

创建完配置节处理程序后,就可以向Web.config文件中配置节声明区域和配置节设置区域添加了,3.1、3.2就是以BlogConfigurationSettings为例讲了配置节声明区域和配置节设置区域这里就不在重复了。

5、访问配置文件中的配置数据

方法一:获取自定义配置对象的一个实例,并使用System.Configuration.ConfigurationManager.GetSection(System.String) 方法。

对于客户端应用程序,此方法检索通过合并应用程序配置文件、本地用户配置文件和漫游配置文件而获得的最终配置文件。GetSection 方法只能访问运行时的配置信息,不能更改这些配置信息。要更改配置,可通过使用下列Open方法中的一种来对所获得的配置文件使用System.Configuration.GetSection 方法:

方法二也是这种情况。

方法二:获取自定义配置对象的一个实例,并使用System.Web.Configuration.WebConfigurationManager.GetSection(System.String) 方法。

方法三:访问<appSettings>中的数据还可以用System.Configuration.ConfigurationManager.AppSettings属性 or System.Web.Configuration.WebConfigurationManager.AppSettings 属性

方法四:访问<connectionStrings>中的数据还可以用System.Configuration.ConfigurationManager.ConnectionStrings属性 or System.Web.Configuration.WebConfigurationManager.ConnectionStrings属性。

当然你可以用DOM来操作web.config文件读取相应的配置数据,不过此方法不推荐。

注意:1、上述方法都是在在.NET Framework 2.0 版中是新增的。

2、其实在DotText中用的是.net 1.x中System.Configuration中的上述方法、属性,如System.Configuration.ConfigurationSettings.GetConfig(sectionName)方法。这些API 现在已过时。

参考文献

【1】微软公司著,《Web应用开发——ASP.NET2.0》38~39页,高等教出版社

【2】MSDN,ASP.NET 配置概述

【3】MSDN,ASP.NET 配置文件

扩展阅读

以下三篇文章是来自codeproject:

【1】Jon RistaUnraveling the Mysteries of .NET 2.0 Configuration

【2】Jon RistaDecoding the Mysteries of .NET 2.0 Configuration

【3】Jon RistaCracking the Mysteries of .NET 2.0 Configuration

百度,Google之后发现没有人翻译,我将翻译了上述三篇文章,翻译工作已经开始,相信不久就会发布,先列出如下:

【4】揭开.NET 2.0配置之谜

【5】解码.NET 2.0配置之谜

【6】破解.NET 2.0配置之谜




本文转自吴秦博客园博客,原文链接:http://www.cnblogs.com/skynet/archive/2010/03/19/1690011.html,如需转载请自行联系原作者

上一篇:SQL Server 即时文件初始化


下一篇:.net如何自定义config配置文件节点