在ASP.NET中使用自定义配置
我们在编写ASP.NET程序的时候,系统的配置数据一般会存储在web.config配置文件中,对于简单的配置我们都使用ASP.NET提供的默认的处理方法:使用appSettings下的add元素,一般会有如下形式
<appSettings>
<add key="Admin" value="Tracy Mac"/>
</appSettings>
这种处理方法对于那些简单的名值对数据的存储非常易用。但是当我们要配置的数据有着比较复杂的结构,如一个列表形式,一个树状结构,使用以上的处理方式就非常难于维护和阅读。
不过ASP.NET提供了自定义配置的功能,允许我们自定义配置节,使我们可以按照自己的元素结构在XML文件中存储配置数据。在.NET Framework 1.1,也就是我们使用Visual Studio 2003的时代时,这种配置功能非常简单,只需要完成一个实现System.Configuration.IConfigurationSectionHandler接口的类就可以了。该接口只有一个Create方法的定义。这种实现自定义配置节的方式几乎没有封装任何功能。我们要做的就是读取从Create方法参数中传递过来的XmlNode对象然后构造我们自己的配置对象并返回。
显然,这种易于学习但不易于使用的开发方式不是微软产品的目标。.NET 2.0已经完全抛弃了这种自定义配置的处理方式。所以,如果你还要使用实现System.Configuration.IConfigurationSectionHandler接口的方法来处理自定义配置,那么你要小心了,使用 .NET Framework 1.0 或 1.1 版生成你的程序才能使你的代码有效。如果使用.NET 2.0的编译器生成你的程序,你的代码将不会执行。.NET 2.0提供了全新的处理方法,这就是下面要讲的。
关于.NET 2.0中的自定义配置节,一些书籍中只是简单介绍了它的使用,非常的不全面。而MSDN虽然非常全面,但是知识点总是零零点点,无法全面的了解它们。所以总结这种自定义配置使用方法真是一件痛苦的事情。废话少说,下面切入正题。
为了完成ASP.NET中自定义配置的功能,需要用到三个主要的类:ConfigurationSection,ConfigurationElementCollection和ConfigurationElement。对它们的描述如下:
类 |
描述 |
ConfigurationSection |
表示配置文件中的节。扩展 ConfigurationSection 类,以提供对自定义配置节的自定义处理和编程访问 |
ConfigurationElementCollection |
表示包含一个子元素集合的配置元素 |
ConfigurationElement |
表示自定义配置节内部的一个元素 |
举例说明,假如我们需要实现一个如下的配置:
<controlsDevelopment>
<regexUrlMapping enable="true" rebaseClientPath="true">
<add url="(/d+)$" mappedUrl="default.aspx?id=$1"></add>
<add url="/$" mappedUrl="default.aspx?id=0"></add>
</regexUrlMapping>
</controlsDevelopment>
在这里controlsDevelopment就是我们要定义的配置节,而配置节里面又包含一个regexUrlMapping元素,该元素有两个属性和一些子元素,我们选择的子元素比较特殊,它是n个add元素。使用的形式跟assSettings元素下面的add元素类似。那么如何实现这个自定义配置呢?
首先需要定义一个配置节元素,如下:
<section name="controlsDevelopment"
type="ControlLibrary.RegexUrlMappingConfig,ControlLibrary"
allowDefinition="Everywhere"
restartOnExternalChanges="true"
allowLocation="true"/>
在这里,我们只讲解name 和type属性的使用,其它属性的用法请参阅MSDN。name属性表示自定义配置节元素的名称。Type表示应该由哪个dll中的哪个类来处理这个配置节。如上例中所写,ControlLibrary是dll的名称,ControlLibrary.RegexUrlMappingConfig是处理该配置节的类的全名称(包含命名空间)。
Ok,我们已经把目的明确了,下面的工作就是要实现RegexUrlMappingConfig这个类。首先建立一个类库项目,命名为ControlLibrary。然后添加一个类,命名为RegexUrlMappingConfig。要想此类拥有处理配置节的能力,就必须装饰一下这个类,装饰完成后,此类的代码如下:
public class RegexUrlMappingConfig : ConfigurationSection
{
[ConfigurationProperty("regexUrlMapping")]
public UrlMappingCollection UrlMappings
{
get
{
return this["regexUrlMapping"] as UrlMappingCollection;
}
}
}
首先,我们的类应该从ConfigurationSection类继承。这样她就有了处理自定义配置信息的能力。由于我们的配置节中只有一个regexUrlMapping元素,而且此元素包含了很多add元素。这种情况下我们使用了一个名为UrlMappings的属性来表示这个集合。为了表示该属性和元素之间的映射关系,我们需要以ConfigurationProperty自定义属性修饰UrlMappings。ConfigurationProperty类的参数” regexUrlMapping”指定了要映射的元素。get访问器中的代码非常程式化,这里不讲它的原理,只需要知道如此就可以实现对数据的访问。
下一步,就是实现UrlMappingCollection类。由名字可以得知,这是一个集合类,它一般用来处理包含add元素的元素。实现此类也需要使用自定义属性对此类进行装饰。如下:
public class UrlMappingCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new UrlMapping();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((UrlMapping)element).Url;
}
[ConfigurationProperty("enable")]
public bool Enable
{
get
{
return bool.Parse(this["enable"].ToString());
}
}
[ConfigurationProperty("rebaseClientPath")]
public bool RebaseClientPath
{
get
{
return bool.Parse(this["rebaseClientPath"].ToString());
}
}
}
可以看到,实现表示集合元素的类必须从ConfigurationElementCollection类继承。并且必须提供CreateNewElement和GetElementKey两个方法的重载。CreateNewElement其实是一个工厂方法,在此方法中,你必须返回一个表示一个add元素的对象,这样系统才能从web.config读取数据并形成一个集合。GetElementKey方法中,你需要返回一个可以表示为add元素键值的属性,方法的参数就是表示add元素的对象,该对象一定是从ConfigurationElement继承的,所以我们可以将其转换为一个我们自定义的配置对象,然后访问它的属性。在示例中我们返回了add远的url属性值。该方法一般由其它方法调用,如BaseGetKey方法等。由于在此我们只讨论只读配置(我们所讲的这些还有很方便的修改web.config的功能。在此我们不做讲述,其实我也不会,也不想深入研究,因为我目前还没有碰到这种需求),所以不再对其做其它讲解。
现在,我们已经实现了需要重写的方法。看到regexUrlMapping元素还包括两个属性,实现这两个属性的代码与已讲过的内容类似。在此不做赘述。
还差最后一步,就是实现表示add元素的类。如下:
public class UrlMapping : ConfigurationElement
{
[ConfigurationProperty("mappedUrl")]
public string MappedUrl
{
get
{
return (string)this["mappedUrl"];
}
}
[ConfigurationProperty("url")]
public string Url
{
get
{
return (string)this["url"];
}
}
}
唯一需要讲述的就是这个类必须从ConfigurationElement继承。其它的内容通过以上的讲述应该能够很好的理解。
好了,我们已经完成了所有的映射工作,最后一件事情就是如何使用我们的自定义配置对象了。使用自定义配置的代码很简单,如下:
object o = ConfigurationManager.GetSection("controlsDevelopment");
RegexUrlMappingConfig config = o as RegexUrlMappingConfig;
获取了表示配置信息的RegexUrlMappingConfig对象,就可以使用其中包含的任何信息了。不过在使用中,我发现,ConfigurationElementCollection对象无法使用索引方便的查找指定的add元素对象。只能使用foreach循环进行查找,或者将集合内容拷贝到一个数组中,只要使用ConfigurationElementCollection.CopyTo方法就可以了。但是我们还有一种更好的方法实现这个功能,就是在UrlMappingCollection类中提供一个索引器,达到按索引访问集合内容的功能,如下:
public UrlMapping this[int i]
{
get
{
return BaseGet(i) as UrlMapping;
}
}
可以看到,只需要在get访问器中调用UrlMappingCollection.BaseGet方法就可以了。