扩展 web.config 配置文件结构

我们知道,使用<appSettings>元素可以保存应用程序使用的自定义信息。但是这个元素有两个明显的限制。

1. 不能保存结构化信息,如列表或一组相关的设置。

2. 不能灵活的处理各种数据类型。这个元素设置只能使用单一的字符串。

 

幸好 ASP.NET 使用一个模块化的高度可扩展的配置模型,它允许你用自定义的节来扩展web.config和machine.config配置文件的结构。

但要执行如下所示的3个步骤:

1. 确定要在配置文件中保存的信息以及如何把它们组织到元素和特性。

2. 对于每个新元素,都创建一个 C#类封装它的信息。

3. 在配置文件里注册新节,必须使用 <configSections> 元素标识每个新元素并把它映射到相关的类。

 

理解上面的理论步骤最好的方式是实践,下面的示例将演示如何在web.config中创建和注册新元素:

(1)创建 Section 类

       假设要保存一组相关设置,它们放在一起会告诉应用程序如何联系远程对象。这些设置可以表示端口号、服务器位置、URL、用户验证信息等。按以前的方法,可以在<appSettings>中单独配置,但是,没有任何东西表明这些信息是相互关联的。这不仅使得设置难以阅读和理解,还可能导致更新了其中一个设置而忘记更新其他相关设置。

       更好的解决办法是摆脱 <appSettings> 节的结构限制而把信息包装在一个单独的 XML 元素中。

<orderService available="true" pollTimeout="00:01:00" location="tcp://OrderComputer:8010/OrderService" />

       使用这种结构,还需要定义一个从 System.Configuration.ConfigurationSection 继承的匹配的类。这个类可以放在独立的DLL组件中,也可以把其源代码放到 App_Code 文件夹中,这样它将作为当前Web程序的一部分被自动编译。

注:GetSection() 方法获取的各种类型都继承自System.Configuration.ConfigurationSection 类!

       下面这个 OrderService 类就是起这个作用的,它代表一个<orderService>元素,通过强类型的属性提供对 3 个特性的访问:

public class OrderService : ConfigurationSection
{
    [ConfigurationProperty("available", IsRequired = false, DefaultValue = true)]
    public bool Available
    {
        get { return (bool)base["available"]; }
        set { base["available"] = value; }
    }
 
    [ConfigurationProperty("pollTimeout", IsRequired = true)]
    public TimeSpan PollTimeout
    {
        get { return (TimeSpan)base["pollTimeout"]; }
        set { base["pollTimeout"] = value; }
    }
 
    [ConfigurationProperty("location", IsRequired = true)]
    public string Location
    {
        get { return (string)base["location"]; }
        set { base["location"] = value; }
    }
}

       可以看到,每个属性都使用了 ConfigurationProperty 特性映射到相应的特性名称。这部分它非常重要,因为它定义了自定义节的架构。如果在自定义节中添加了一个特性但没有匹配的 ConfigurationProperty 特性,那么读取 web.config 文件时,ASP.NET 就会抛出一个异常

       ConfigurationProperty 特性的 IsRequired 属性还能让你决定哪些信息是必需的,如果没有提供默认值,你还可以决定使用什么样的默认值

 

(2)注册 Section 类

       创建了 Section 后,编码工作就算完成了,不过,还需要在 web.config 文件里注册 Section 类,这样 ASP.NET 才能识别自定义设置。否则运行应用程序将会出错,将提示在 web.config 文件中发现无法识别的节。

       只要在 web.config 文件的<configSections>节中添加一个<section>元素就可以注册自定义节,但还必须指定节的名称(通过name特性),指定对应类的名字(通过type特性)。

<configuration>
  <configSections>
    <section name="orderService" type="OrderService"/>
  </configSections>
  
    <system.web>
  <compilation debug="true" targetFramework="4.0"/>
    <trace enabled="true" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true" />
    </system.web>
 
  <orderService available="true" pollTimeout="00:01:00" location="tcp://OrderComputer:8010/OrderService" />
</configuration>

 

(3)编写代码在 Web 页面中获取自定义节的信息

protected void Page_Load(object sender, EventArgs e)
{
    object obj = ConfigurationManager.GetSection("orderService");
    OrderService os = obj as OrderService;
    Label1.Text += "Retrieved service information ...<br />"
                + "<b>Location:</b> " + os.Location
                + "<br /><b>Available:</b> " + os.Available
                + "<br /><b>Timeout:</b> " + os.PollTimeout + "<br /><br />";
}

页面展现:

image

 

 

再次扩展自定义配置节

       自定义配置节还可以更为复杂一些,例如,创建一个具有嵌套子元素的节。看下面示例:

<orderService available="true" pollTimeout="00:01:00">
  <location computer="OrderComputer" port="8010" endpoint="OrderService" />
</orderService>

       如果使用这样的结构,只要创建一个从 ConfigurationElement 继承的类来代表每个嵌套元素即可

/// <summary>
/// 嵌套的子元素必须继承自 ConfigurationElement 类 
/// </summary>
public class Location : ConfigurationElement
{
    [ConfigurationProperty("computer", IsRequired = true)]
    public string Computer
    {
        get { return (string)base["computer"]; }
        set { base["computer"] = value; }
    }
 
    [ConfigurationProperty("port", IsRequired = true)]
    public int Port
    {
        get { return (int)base["port"]; }
        set { base["port"] = value; }
    }
 
    [ConfigurationProperty("endpoint", IsRequired = true)]
    public string Endpoint
    {
        get { return (string)base["endpoint"]; }
        set { base["endpoint"] = value; }
    }
}

原先的 OrderService 类修改成这样:

public class OrderService : ConfigurationSection
{
    [ConfigurationProperty("available", IsRequired = false, DefaultValue = true)]
    public bool Available
    {
        get { return (bool)base["available"]; }
        set { base["available"] = value; }
    }
 
    [ConfigurationProperty("pollTimeout", IsRequired = true)]
    public TimeSpan PollTimeout
    {
        get { return (TimeSpan)base["pollTimeout"]; }
        set { base["pollTimeout"] = value; }
    }
 
    [ConfigurationProperty("location", IsRequired = true)]
    public Location Location // 这里的属性是子元素类型
    {
        get { return (Location)base["location"]; }
        set { base["location"] = value; }
    }
}

这里调用一下:

protected void Page_Load(object sender, EventArgs e)
{
    object obj = ConfigurationManager.GetSection("orderService");
    OrderService os = obj as OrderService;
    Label1.Text += "Retrieved service information ...<br />"
                + "<br /><b>Available: </b>" + os.Available
                + "<br /><b>Timeout: </b>" + os.PollTimeout + "<br /><br />"
                + "<b>Server: </b>" + os.Location.Computer + "<br />"
                + "<b>Port: </b>" + os.Location.Port + "<br />"
                + "<b>Endpoint: </b>" + os.Location.Endpoint + "<br />";
}

最后的效果:

image

posted on 2012-07-10 14:00  SkySoot  阅读(2005)  评论(0编辑  收藏  举报

导航