在ASP.NET中使用自定义配置

时间:2022-12-06 12:19:15

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中自定义配置的功能,需要用到三个主要的类:ConfigurationSectionConfigurationElementCollectionConfigurationElement。对它们的描述如下:

 

描述

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元素,该元素有两个属性和一些子元素,我们选择的子元素比较特殊,它是nadd元素。使用的形式跟assSettings元素下面的add元素类似。那么如何实现这个自定义配置呢?

首先需要定义一个配置节元素,如下:

<section name="controlsDevelopment"

type="ControlLibrary.RegexUrlMappingConfig,ControlLibrary"

allowDefinition="Everywhere"

restartOnExternalChanges="true"

allowLocation="true"/>

在这里,我们只讲解name type属性的使用,其它属性的用法请参阅MSDNname属性表示自定义配置节元素的名称。Type表示应该由哪个dll中的哪个类来处理这个配置节。如上例中所写,ControlLibrarydll的名称,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自定义属性修饰UrlMappingsConfigurationProperty类的参数” 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类继承。并且必须提供CreateNewElementGetElementKey两个方法的重载。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方法就可以了。