自定义配置节
Custom Configuration Sections
除了预先定义好的配置节之外,还可以添加自定义配置节。可添加两种不同类型的自定义配置节:
l 提供对Name/Value对集合访问的配置节,类似于appSettings
l 返回任何对象类型的配置节
本节将对以上两者进行讲解。
Name/Value对
返回示例18-10,添加一个配置节,将包含ISBN号和标题的字符串存储其中。假设需要为多个数据库存储连接字符串,一个名为Test(用于测试目的),一个名为Content(存储产品信息)。在这种情况下,使用自定义配置节是返回name/value对的处理方法。
示例18-13显示了插入到web.config中的最终版本的代码行。添加一个返回name/value对的自定义配置节有三个步骤:
1. 确定把自定义配置节添加到哪个具体的配置文件中。正如在层次化配置一节中所描述的那样,需要确定自定义节的范围或者可见性。
向 machine.config或者机器级别的web.config添加配置节,可以将它应用到机器上所有应用程序。向默认网站(c:\inetpub \wwwroot)的web.config文件添加配置节,可以将它应用到默认网站下的每个站点。向应用程序根目录下的web.config文件添加配置节,可以将它应用到整个应用程序,但不包括其他应用程序。向应用程序子目录下的web.config文件添加配置节,可以将它应用到这个子目录及其下的子目录。
2. 通过向指定配置文件的配置节添加一行,可以声明此配置节的处理程序。它告诉ASP.NET以指定的名字和类接受此配置节,并且使用程序集文件处理此配置节。
向指定配置文件的内添加示例18-13中的高亮显示行。如果所编辑的文件没有标记,那么就把它们一起添加上。必须是配置节的第一个子配置节。
3. 向配置文件添加自定义配置节。这由示例18-13中标记之间的高亮部分组成。这个自定义配置节包括两个项,一个命名为Test,另一个命名为Content,它们都具有自己的属性值。
示例18-13:web.config中的自定义配置节
配置节中的type属性用于指定System.dll程序集文件中的Dictionary- SectionHandler类。更多有关的文档,参见SDK文件,检索“Custom Elements”,并选择“Custom Element for NameValueSectionHandler”。
为了读取自定义配置节的内容,可使用ConfigurationManager类的GetSection方法。完成此功能的代码如示例18-14高亮部分所示。此处假定内容页中有两个Label控件:lblTest和lblContent。在代码隐藏文件顶部声明引入System.Collections名字空间。这样就不必在使用Hashtable对象时,必须写一个完全限定的名字。
示例18-14:读取自定义配置值
using System.Collections; //对Hashtable必要
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string strTest;
strTest = ((Hashtable)ConfigurationManager.
GetSection("altDB"))["Test"].ToString( );
lblTest.Text = strTest;
lblContent.Text = ((Hashtable)ConfigurationManager.
GetSection("altDB"))["Content"].ToString( );
}
}
示例18-14说明了两个等效的显示键值的内容的方法。一种方法是先把值赋给一个字符串,然后再把字符串赋给Label控件的Text属性。另一种方法是直接赋值给Text属性。尽管后一种更简练,但前者更多的时候有利于调试。
GetSection方法将需要获取的配置节名字作为一个参数,然后返回一个Hashtable类型的对象。使用get属性语法,在Collection中利用一个偏移量检索期望值。在C#中,此属性使用方括号来检索。
C#代码首先计算或者转换由GetSection方法返回的值,因为C#不支持后期绑定。另外,由于返回值是对象类型,所以必须使用静态ToString方法将它转换为字符串。
对象
appSettings和自定义配置节都非常有用。然而,它们都受限于只能返回Name/Value对。有时候,返回一个对象会更加有用。
例如,假设需要在数据库中执行一个标准查询。可以将查询字符串存储在appSetti- ngs标记中,然后返回该字符串并打开数据库连接。然而,更方便的方法是,将查询字符串存储在web.config文件,然后使配置系统直接返回一个DataSet。
为了实现以上内容,必须在指定配置文件中添加一个标记和一个配置节,这个过程与上节所介绍的自定义配置节返回Name/Value对一样。
编辑前一个示例18-14中使用的web.config文件,添加示例18-15中高亮显示的代码。
示例18-15:在web.config中自定义返回对象的配置节
.
.
.
.
.
.
在 配置节的子配置节中,为system.web组的DataSetSectionHandler创建了一个处理程序声明。这样就指定了在这个文件的system.web配置节中将有一个名为DataSetSectionHandler的自定义配置节。此外,
它还指定了处理这个配置节的类DataSetSectionHandler,而这个类包含在bin目录中的程序集文件SectionHandlers.dll中。
另外,在这个文件的配置节中有一个名为DataSetSectionHandler配置节。该配置节仅包括一个str属性。其中的字符串是传递给数据库的SQL语句。
接下来必须创建DataSetSectionHandler类,它位于SectionHandler.cs文件中。为此,在VS2005的解决方案资源管理器中,右击应用程序根目录。选择添加新项,接着选择一个新类并命名为SectionHandlers.cs。添加示例18-16中高亮显示的代码。
示例18-16:SectionHandler.cs
using System;
using System.Data;
using System.Data.SqlClient; // 对数据访问必要
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public class DataSetSectionHandler : IConfigurationSectionHandler
{
public Object Create(Object parent,
Object configContext,
System.Xml.XmlNode section)
{
string strSql;
strSql = section.Attributes.Item(0).Value;
string connectionString = "server=MyServer; uid=MyID; " +
"pwd=secret; database=Northwind";
// 创建数据集命令对象和DataSet
SqlDataAdapter da = new SqlDataAdapter(strSql,
connectionString);
DataSet dsData = new DataSet( );
// 填充数据,设置对象
da.Fill(dsData, "Customers");
return dsData;
}
}
为了与示例18-15列举的web.config中的类名匹配,类名已经更改为DataSetSec- tionHandler。该类继承自IconfigurationSectionHandler。
提示:设置连接字符串以匹配指定的数据库。服务器名和密码当然与示例18-16中显示的不同。
第9章和第10章中完整介绍了示例中数据库方面的代码。
对于一个作为配置节处理程序的类,必须实现IConfigurationSectionHandler接口。在C#中,使用类或方法和被继承的类或接口之间的冒号表示。
提示:有关完整的讨论面向对象的基本概念,例如继承、基类和接口,超出了本书范围。当前,仅需要了解接口相当于实现类必须遵守的合同。例如,接口指示实现类必须实现的方法的特征,或者指示该类必须提供哪些属性。
IConfigurationSectionHandler接口只有一个Creat方法。因此,实现类必须实现具有指定特征的Create方法。接口指定了方法的三个参数。前两个参数很少用,在这里也不做深入讨论。第三个参数是来自配置文件的XML数据。
解析XML节点,在Attributes集合中的第一项将被赋予一个字符串变量,如下所示:
strSql = section.Attributes.Item(0).Value
一旦获取了SQL字符串和硬编码的连接字符串,那么将初始化一个SqlDataAdapter对象并执行,接着填充并返回DataSet。
类在使用前必须经过编译,并将其存储在应用程序根目录下的bin目录的应用程序集缓存中。
警告:引用中type属性指定的程序集,必须进行预编译,应用程序才可使用。不能仅仅把类源代码放在App_Code目录中让它在运行时自动编译。和普通的操作一样,编译要求有集合的名字,而不仅仅是它的内容。
单击开始 > Microsoft Visual Studio 2005 > Visual Studio Tools > Visual Studio 2005命令提示,打开一个DOS命令窗口。使用cd命令把当前目录设置为应用程序根目录。假定应用程序根目录已经有一个名为bin的子目录。如果没有,则新建一个。然后输入以下命令行(不要换行):
csc /t:library /out:bin\SectionHandlers.dll
/r:system.dll,System.data.dll,System.xml.dll SectionHandlers.cs
输出目标类型被设置为类库,也就是dll。输出文件存储在bin目录中,名称为Section- Handlers.dll。同时,还引用了3个dll文件。输入源文件是SectionHandler.cs。当编译源文件时,将dll输出到bin目录中,此处的类将自动为应用程序使用。
利用自定义配置节的典型方法是,先在页面上放置一个GridView控件,然后从配置节返回数据集,并与其绑定。假设GridView控件被命名为gv,示例18-17中列出的代码将从数据库中返回数据,并将其绑定到控件。
示例18-17:返回自定义配置对象的代码隐藏文件
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
CreateGrid( );
}
}
private void CreateGrid( )
{
DataSet dsGrid = new DataSet( );
dsGrid = (DataSet)ConfigurationManager.
GetSection("system.web/DataSetSectionHandler");
gv.DataSource = dsGrid.Tables[0];
gv.DataBind( );
}
示例18-17中有趣的工作是使用CreateGrid方法来完成。该方法没有提供连接字符串和SQL查询字符串,而是调用 ConfigurationManage类的GetSection方法,直接返回一个DataSet对象。GridView控件的数据源设置为 DataSet对象,然后控件执行数据绑定。GetSection方法的参数是包含配置设置的配置节名称的字符串。节(system.web)与子节(DataSetSectionHandler)的名字从语法上用一个斜线隔开