DNN学习笔记 之一 配置
创 建 人:pblee
创建实践:2006-6-28
文档名称:DNN学习笔记1
关 键 字:DNN 源码分析 配置
DNN是一个开放的平台,不仅仅是源代码,它支持所有用户自定义组件并挂接到主引擎上。正因为它的开放特性,使得它的使用者与日俱增。
本学习笔记基于DNN 4.3源码,该项目使用.net框架2.0,这样在学习代码的同时也可以学习.net 2.0的新特性。
先从配置文件开始
代码片断1 release.config
< sectionGroup name ="dotnetnuke" >
<!-- the requirePermission attribute will cause a syntax warning - please ignore - it is required for Medium Trust support -->
< section name ="data" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="logging" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="scheduling" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="htmlEditor" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="navigationControl" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="searchIndex" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="searchDataStore" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="friendlyUrl" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="caching" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="authentication" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="members" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="roles" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
< section name ="profiles" requirePermission ="false" type ="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke" />
</ sectionGroup >
</ configSections >
对于configSessions元素MSDN2003的解释并不深入
[引用:ms-help://MS.MSDNQTR.2003FEB.2052/cpgenref/html/gngrfconfigsectionselementcontainertag.htm]
备注
如果此元素在配置文件中,则它一定是 <configuration> 元素的第一个子元素。
[引用结束]
MSDN2005的解释:
[引用:ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/dv_ASPNETgenref/html/8a5cbc84-0257-4c2e-80a9-a064fe7c896b.htm]
指定配置节和命名空间声明。
<configSections>
<section />
<sectionGroup />
<remove />
<clear/>
</configSections>
子元素
元素 说明
clear
移除对继承的节和节组的所有引用,只允许由当前 section 和 sectionGroup 元素添加的节和节组。
remove
移除对继承的节和节组的引用。
section
定义配置节处理程序与配置元素之间的关联。
sectionGroup
定义配置节处理程序与配置节之间的关联。
备注
configSections 元素指定了配置节和处理程序声明。由于 ASP.NET 不对如何处理配置文件内的设置作任何假设,因此这非常必要。但 ASP.NET 会将配置数据的处理委托给配置节处理程序。
每个 section 元素标识一个配置节或元素以及对该配置节或元素进行处理的关联 ConfigurationSection 派生类。可以在 sectionGroup 元素中对 section 元素进行逻辑分组,以对 section 元素进行组织并避免命名冲突。section 和 sectionGroup 元素包含在 configSections 元素中。
如果配置文件中包含 configSections 元素,则 configSections 元素必须是 configuration 元素的第一个子元素。
[引用结束]
打开Machine.Config文件可以看到我们常用的一些节的定义,比如:
代码片断2 Machine.config
< section name ="appSettings" type ="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges ="false" requirePermission ="false" />
< section name ="connectionStrings" type ="System.Configuration.ConnectionStringsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" requirePermission ="false" />
< sectionGroup name ="system.web" type ="System.Web.Configuration.SystemWebSectionGroup, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" >
< section name ="anonymousIdentification" type ="System.Web.Configuration.AnonymousIdentificationSection, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" allowDefinition ="MachineToApplication" />
< section name ="authentication" type ="System.Web.Configuration.AuthenticationSection, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" allowDefinition ="MachineToApplication" />
……省略一段……
</ sectionGroup >
也就是说其实config配置文件最重要的地方就是configSections,没有它我们配置的东西程序不知道如何去处理。做个试验。
新建一个web项目,在默认生成的web.config的<configuration>元素中加入如下代码。
示例代码1.1
< add key ="ServerName" value ="WWW.GOOGLE.COM" />
</ appSettings >
再在页面Page_Load()中加入如下代码:
示例代码1.2
{
Response.Write(System.Configuration.ConfigurationSettings.AppSettings[ " ServerName " ]);
}
浏览页面,很简单,我们看到了配置中写下的内容,"WWW.GOOGLE.COM",这个相信很多人都已经会用了
下面我们做点小破坏,删除machine.config中<appSettings>的定义
注意#删除前确保已经备份源文件,我们还需要改回来的。
保存machine.config,再刷新刚才的页面,出现错误了:
配置错误
说明: 在处理向该请求提供服务所需的配置文件时出错。请检查下面的特定错误详细信息并适当地修改配置文件。
分析器错误信息: 无法识别的配置节 appSettings。
这个节没有在web.config以及它继承的machine.config找到定义。
再改改,把上面删除的部分添加到web.config相应位置,再刷新,显示又正常了。小心,因为你删除了默认配置,这样其他本地运行的程序因为还在使用默认配置而没有在web.config中独立添加<appsettings>的定义,所有使用它的程序将无法正常使用。把原来的machine.config还原回去吧。
现在我们知道了,所有在web.config中定义的除<configSections>节以外的元素都要从config文件中定义,包括web.config和它所继承的machine.config。
OK,我们已经找到起始点了。下面停顿几秒钟,试着解释一下下面的定义,然后继续往下看。
<section name="data" requirePermission="false" type="DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke"/>
是的,它声明了一个节,并告诉CLR如果碰到一个名叫<data>的节将调用"DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke"进行处理。.net FrameWork 为我们提供了一些简单的配置节处理类库,参见System.Configuration命名空间。
<section>的RequirePermission属性可以参见MSDN
http://msdn2.microsoft.com/zh-CN/library/system.configuration.sectioninformation.requirepermission.aspx
当然,下面那些定义基本相同,现在我们只关注<data>,先看看它里面有什么属性,这样在我们找到处理程序的时候就可以知道它将处理哪些参数了。
代码片断3 release.config
defaultProvider ="SqlDataProvider" >
< providers >
< clear />
< add
name ="SqlDataProvider"
type ="DotNetNuke.Data.SqlDataProvider, DotNetNuke.SqlDataProvider"
connectionStringName ="SiteSqlServer"
upgradeConnectionString =""
providerPath ="~/Providers/DataProviders/SqlDataProvider/"
objectQualifier =""
databaseOwner ="dbo" />
</ providers >
</ data >
再看看DotNetNuke.Framework.Providers.ProviderConfigurationHandler如何处理这些配置
代码片断4 DotNetNuke.Library/Components/Providers/ProviderConfigurationHandler.vb
Implements IConfigurationSectionHandler
Public Overridable Overloads Function Create( ByVal parent As Object , ByVal context As Object , ByVal node As System.Xml.XmlNode) As Object Implements IConfigurationSectionHandler.Create
Dim objProviderConfiguration As New ProviderConfiguration
objProviderConfiguration.LoadValuesFromConfigurationXml(node)
Return objProviderConfiguration
End Function
End Class
类实现了IConfigurationSectionHandler接口,此接口只有一个方法
Object Create (
Object parent,
Object configContext,
XmlNode section
)
此方法的说明参见MSDN 2005
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref4/html/M_System_Configuration_IConfigurationSectionHandler_Create_2_23718a01.htm
[引用MSDN2005]
您可以用自己的 XML 配置元素来扩展标准的 ASP.NET 配置设置集。若要完成该操作,您必须创建自己的配置节处理程序。
该处理程序必须是一个实现 System.Configuration.IConfigurationSectionHandler 接口或 System.Configuration.ConfigurationSection 类的 .NET Framework 类。
[引用结束]
好,继续看ProviderConfigurationHandler的实现
Dim objProviderConfiguration As New ProviderConfiguration
objProviderConfiguration.LoadValuesFromConfigurationXml(node)
Return objProviderConfiguration
ProviderConfiguration里的代码就不贴出了,他内部包含了一个HashTable,并将配置信息保存在里面。
这样在程序初始化时就会自动获取配置信息了。那么这个配置如何得到呢?通过System.Configuration.ConfigurationManager类的GetSection方法。需要注意的是此类在.net 1.1中不存在,1.1中使用System.Configuration.ConfigurationSettings.GetSection()得到同样的效果,但是此方法在2.0中标志为已过期,也就是.net不保证其向后兼容。
详细资料还请参阅MSDN2005
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref4/html/T_System_Configuration_ConfigurationManager.htm
好了,在我们继续学习DNN的配置处理之前演练一下我们学到的东西:
示例代码3 web.config
< section name ="Name" type ="MySectionHandler" />
</ configSections >
< Name FirstName ="Bill" LastName ="Gates" />
定义节,并为它设置了属性
示例代码4 MySectionHandler.cs
{
IConfigurationSectionHandler 成员#region IConfigurationSectionHandler 成员
public object Create(object parent, object configContext, System.Xml.XmlNode section)
{
Hashtable configtable = new Hashtable();
foreach (XmlAttribute att in section.Attributes)
{
configtable.Add(att.Name, att.Value);
}
return configtable;
}
#endregion
}
现在我们实现了接口
示例代码5 Default.aspx.cs
{
Hashtable myconfig = (Hashtable)System.Configuration.ConfigurationManager.GetSection( " Name " );
Response.Write( " FirstName: " + myconfig[ " FirstName " ].ToString() + " <BR> " );
Response.Write( " LastName: " + myconfig[ " LastName " ].ToString() );
}
获取配置信息。