如何定义带有潜在子元素和属性的自定义web.config部分?
我开发的Web应用程序通常需要相互依赖的配置设置,并且在我们在每个环境之间移动时,有些设置也必须更改。
目前,我们所有的设置都是简单的键值对,但创建自定义配置节将非常有用,这样,当两个值需要一起更改时或者针对环境需要更改设置时,这一点很明显。
创建自定义配置节的最佳方法是什么,检索值时有什么特别的注意事项?
解决方案
回答
我们可以使用节处理程序来完成此操作。关于如何编写一个基本概述,请访问http://www.codeproject.com/KB/aspnet/ConfigSections.aspx,但是它指的是app.config,与编写一个用于Web的代码几乎相同。配置。这实际上将使我们在配置文件中拥有自己的XML树并进行一些更高级的配置。
回答
Quick'n Dirty:
首先创建ConfigurationSection和ConfigurationElement类:
public class MyStuffSection : ConfigurationSection { ConfigurationProperty _MyStuffElement; public MyStuffSection() { _MyStuffElement = new ConfigurationProperty("MyStuff", typeof(MyStuffElement), null); this.Properties.Add(_MyStuffElement); } public MyStuffElement MyStuff { get { return this[_MyStuffElement] as MyStuffElement; } } } public class MyStuffElement : ConfigurationElement { ConfigurationProperty _SomeStuff; public MyStuffElement() { _SomeStuff = new ConfigurationProperty("SomeStuff", typeof(string), "<UNDEFINED>"); this.Properties.Add(_SomeStuff); } public string SomeStuff { get { return (String)this[_SomeStuff]; } } }
然后,让框架知道如何处理web.config中的配置类:
<configuration> <configSections> <section name="MyStuffSection" type="MyWeb.Configuration.MyStuffSection" /> </configSections> ...
并在下面添加我们自己的部分:
<MyStuffSection> <MyStuff SomeStuff="Hey There!" /> </MyStuffSection>
然后,我们可以在代码中使用它,因此:
MyWeb.Configuration.MyStuffSection configSection = ConfigurationManager.GetSection("MyStuffSection") as MyWeb.Configuration.MyStuffSection; if (configSection != null && configSection.MyStuff != null) { Response.Write(configSection.MyStuff.SomeStuff); }
回答
使用属性,子配置节和约束
还可以使用自动处理管道的属性,并提供轻松添加约束的功能。
我在这里展示了我在一个站点中使用的代码示例。有一个约束,我决定允许任何一个用户使用的最大磁盘空间量。
MailCenterConfiguration.cs:
namespace Ani { public sealed class MailCenterConfiguration : ConfigurationSection { [ConfigurationProperty("userDiskSpace", IsRequired = true)] [IntegerValidator(MinValue = 0, MaxValue = 1000000)] public int UserDiskSpace { get { return (int)base["userDiskSpace"]; } set { base["userDiskSpace"] = value; } } } }
像这样在web.config中设置
<configSections> <!-- Mailcenter configuration file --> <section name="mailCenter" type="Ani.MailCenterConfiguration" requirePermission="false"/> </configSections> ... <mailCenter userDiskSpace="25000"> <mail host="my.hostname.com" port="366" /> </mailCenter>
子元素
子xml元素邮件是在与上述相同的.cs文件中创建的。在这里,我在端口上添加了约束。如果为端口分配的值不在此范围内,则在加载配置时,运行时将报错。
MailCenterConfiguration.cs:
public sealed class MailCenterConfiguration : ConfigurationSection { [ConfigurationProperty("mail", IsRequired=true)] public MailElement Mail { get { return (MailElement)base["mail"]; } set { base["mail"] = value; } } public class MailElement : ConfigurationElement { [ConfigurationProperty("host", IsRequired = true)] public string Host { get { return (string)base["host"]; } set { base["host"] = value; } } [ConfigurationProperty("port", IsRequired = true)] [IntegerValidator(MinValue = 0, MaxValue = 65535)] public int Port { get { return (int)base["port"]; } set { base["port"] = value; } }
使用
要在代码中实际使用它,我们要做的就是实例化MailCenterConfigurationObject,这将自动从web.config中读取相关部分。
MailCenterConfiguration.cs
private static MailCenterConfiguration instance = null; public static MailCenterConfiguration Instance { get { if (instance == null) { instance = (MailCenterConfiguration)WebConfigurationManager.GetSection("mailCenter"); } return instance; } }
AnotherFile.cs
public void SendMail() { MailCenterConfiguration conf = MailCenterConfiguration.Instance; SmtpClient smtpClient = new SmtpClient(conf.Mail.Host, conf.Mail.Port); }
检查有效性
我之前提到过,运行时会在加载配置时抱怨,并且某些数据不符合我们设置的规则(例如MailCenterConfiguration.cs中的规则)。我倾向于在我的网站启动时尽快了解这些事情。解决此问题的一种方法是将配置加载到_Global.asax.cx.Application_Start_中,如果配置无效,则会通过异常的方式通知我们。网站将无法启动,相反,我们会在死亡的黄屏中看到详细的异常信息。
Global.asax.cs
protected void Application_ Start(object sender, EventArgs e) { MailCenterConfiguration.Instance; }
回答
自定义配置非常方便,并且通常应用程序最终需要可扩展的解决方案。
对于.NET 1.1,请参阅文章http://aspnet.4guysfromrolla.com/articles/020707-1.aspx
注意:上述解决方案也适用于.NET 2.0。
有关.NET 2.0特定解决方案,请参阅文章http://aspnet.4guysfromrolla.com/articles/032807-1.aspx