专栏首页.Net Core技术分享创建自定义配置节点(web.config和app.config都适用)

创建自定义配置节点(web.config和app.config都适用)

  恼火!不小心点到全屏幕模式,刚写的东西全丢了!!从头再来!!!

  无论是web程序、windows程序、windows service程序,配置文件都是少不了的。我们都习惯了将连接字符串放在ConnectionString节点中,将程序的设置放在appSetting节点中。配置文件的管理程序为我们提供了方便的管理方式,那么,我们如何自定义配置节点呢?

  有两种方法,其一,继承IConfigurationSectionHandler,通过实现Create方法。这种方法的灵活度非常大,我们需要动手解析自定义节点的XmlNode,所以,实现起来也比较复杂。其二,继承ConfigurationSection,这种方法就简单多了,只需要指定对应的属性名称即可。

  本文旨在使用最少的代码实现自定义配置节点,所以果断放弃第一种方法,使用第二种方法实现自定义配置节点。

  光说不练假把式,接下来我们就着手使用第二种方法实现自定义配置节点。步骤如下:

  1.在configSections节点中定义自定义配置节点信息

  <configSections>
    <section name="custom" type="SampleWebConfigSection.Configuration.customSection, SampleWebConfigSection" />
  </configSections>
  • name:自定义配置节点的名称
  • type:类型,自定义配置节点对应的数据类型

  2.完成自定义配置节点的结构

<custom fileName="Default.txt" maxUsers="2500" maxIdleTime="00:10:00" />

  3.编程实现节点的访问

using System.Configuration;
using System;

namespace SampleWebConfigSection.Configuration
{
    public class customSection : ConfigurationSection
    {
        [ConfigurationProperty("fileName", DefaultValue = "default.txt", IsRequired = true, IsKey = false)]
        [StringValidator(InvalidCharacters = " ~!@#$%^&*()[]{}/;'\"|\\", MinLength = 1, MaxLength = 60)]
        public string FileName
        {
            get { return (string)this["fileName"]; }
            set { this["fileName"] = value; }
        }

        [ConfigurationProperty("maxUsers", DefaultValue = (long)10000, IsRequired = false)]
        [LongValidator(MinValue = 1, MaxValue = 10000000, ExcludeRange = false)]
        public long MaxUsers
        {
            get { return (long)this["maxUsers"]; }
            set { this["maxUsers"] = value; }
        }

        [ConfigurationProperty("maxIdleTime", DefaultValue = "0:10:0", IsRequired = false)]
        [TimeSpanValidator(MinValueString = "0:0:30", MaxValueString = "5:00:0", ExcludeRange = false)]
        public TimeSpan MaxIdleTime
        {
            get { return (TimeSpan)this["maxIdleTime"]; }
            set { this["maxIdleTime"] = value; }
        }
    }
}
  • ConfigurationProperty标记:指示 .NET Framework 通过custom节点的属性来实例化对象的字段值。对于每一个标记有此特性的属性,.NET Framework 都使用反射来读取修饰参数,并创建相关的 ConfigurationProperty 实例。
  • StringValidator标记:以声明的方式指示 .NET Framework 对配置属性执行字符串验证。
  • LongValidator标记:以声明的方式指示 .NET Framework 对配置属性执行长整型验证。
  • TimeSpanValidator标记:以声明的方式指示 .NET Framework 对配置属性执行时间验证。

  4.自定义配置节点的使用

    customSection custom = (customSection)System.Configuration.ConfigurationManager.GetSection("custom");
    Response.Write(custom.FileName + "|" + custom.MaxUsers.ToString() + "|" + custom.MaxIdleTime);

  在第一句代码中,我们通过ConfigurationManager.GetSection获取custom节点,并强制类型转换为我们自定义的节点,这样就能够方便的使用了。

  OK,第一个例子完成。其实这个例子是MSDN中的,我将它拿下来,稍加说明而已。

  当然,只有上面这些内容是不足以放首页的。上面的例子并不能完全满足我们常规的需求,甚至我们可以把这些配置放在appSetting中来替代我们的自定义配置节点。下面介绍一个实际的需求:

  在网站的建设中,我们希望将网站的标题、副标题和网址放在一条配置中,因为网站有文件上传功能,我们希望在配置中限制上传文件的大小,并针对不同的上传类型将文件放在不同的目录中。定以后的节点结构如下:

  <webSetting>
    <base title="草屋&amp;拾荒" subTitle="七千米深蓝的博客" url="http://youring2.cnblogs.com"></base>
    <fileUpload>
      <file name="headPhoto" path="upload/image/headPhoto" size="200"></file>
      <file name="album" path="upload/image/album" size="1024"></file>
    </fileUpload>
  </webSetting>

  要完成这个自定义配置节点,按照第一个例子的步骤,我们需要现在configSections中配置自定义节点信息:

<section name="webSetting" type="SampleWebConfigSection.Configuration.webSettingSection, SampleWebConfigSection" />

  不解释,接下来我们需要完成四个类:

  • webSettingSection
  • baseSection
  • fileUploadSection
  • fileSection

  这四个类分别对应这个配置中的四个节点:webSetting、base、fileUpload和file。

using System.Configuration;

namespace SampleWebConfigSection.Configuration 
{
    public class webSettingSection : ConfigurationSection
    {
        //base节点
        [ConfigurationProperty("base")]
        public baseSection BaseSetting { get {return (baseSection)base["base"]; } }

        //fileUpload节点
        [ConfigurationProperty("fileUpload")]
        public fileUploadSection FileUploadSetting { get { return (fileUploadSection)base["fileUpload"]; } }
    }
}

  派生自ConfigurationSection,包含两个属性:BaseSetting和FileUploadSetting,这两个属性分别对应配置文件中的两个子节点base 和fileUpload。

using System.Configuration;

namespace SampleWebConfigSection.Configuration
{
    public class baseSection : ConfigurationElement
    {
        //title属性
        [ConfigurationProperty("title", IsKey = true, IsRequired = true)]
        public string title { get { return (string)base["title"]; } set { title = value; } }
        //subTitle属性
        [ConfigurationProperty("subTitle",  IsRequired = false, DefaultValue="")]
        public string subTitle { get { return (string)base["subTitle"]; } set { subTitle = value; } }
        //url属性
        [ConfigurationProperty("url", IsRequired = true)]
        public string url { get { return (string)base["url"]; } set { url = value; } }
    }
}

  派生自ConfigurationElement,因为它是一个子元素,被包含在webSettingSection类中。它的几个属性不作解释。

using System.Configuration;

namespace SampleWebConfigSection.Configuration
{
    [ConfigurationCollection(typeof(fileSection), AddItemName = "file")]
    public class fileUploadSection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new fileSection();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((fileSection)element).name;
        }

        public fileSection this[int index]
        {
            get { return (fileSection)base.BaseGet(index); }
        }

        new public fileSection this[string name]
        {
            get { return (fileSection)base.BaseGet(name); }
        }
    }
}

  派生自ConfigurationElementCollection,因为它是一个子元素的集合,它包含一个fileSection的集合。

  这个类使用了如下的标记:

[ConfigurationCollection(typeof(fileSection), AddItemName = "file")]

  这是一个子元素集合的说明,第一个type参数是必须的,它指定了包含子集的类型。第二个参数是可选的,它指定了要添加到集合中的子节点的节点名,默认是是add,我们没有使用默认值,而是使用了“file”,所以在这里进行了指定。

  另外,这个类还实现了通过index和name获取一个fileSection的方法,分别是this[int index]和this[string name]。基类本身存在通过字符串获取子元素的方法,所以这里要使用new关键字。

using System.Configuration;

namespace SampleWebConfigSection.Configuration
{
    public class fileSection : ConfigurationElement
    {
        //name属性
        [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
        public string name { get { return (string)this["name"]; } set { name = value; } }
        //path属性
        [ConfigurationProperty("path", IsRequired = true)]
        public string path { get { return (string)this["path"]; } set { path = value; } }
        //size属性
        [ConfigurationProperty("size", IsRequired = true, DefaultValue = 1024)]
        public int size { get { return (int)this["size"]; } set { size = value; } }
    }
}

  派生自ConfigurationElement。它的属性很简单,不解释。

  我们可以使用如同第一个示例中使用自定义配置节点的方法使用这个配置节点。但通常我们不希望每次使用的时候都重新加载一次配置项,所以,我们通过一个静态对象来访问这个配置节点:

namespace SampleWebConfigSection.Configuration
{
    public class WebSettingManager
    {
        public static webSettingSection WebSetting = (webSettingSection)System.Configuration.ConfigurationManager.GetSection("webSetting");
    }
}

  测试一下我们的自定义配置节点是否好使,在网站的页面中加入如下代码:

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <h2>
        <asp:Label ID="lblTitle" Text="" runat="server" />
    </h2>
    <h3>
         <asp:Label ID="lblSubTitle" Text="" runat="server" />
    </h3>
    地址:<asp:Label ID="lblUrl" Text="" runat="server" />
    <p></p><p></p>
    <asp:GridView ID="gvFileUploadSetting" runat="server" Width="300" BackColor="#F0F8FF" AutoGenerateColumns="false">
        <Columns>
            <asp:TemplateField HeaderText="名称">
                <HeaderStyle Width="80px" Font-Bold="true" />
                <ItemStyle Font-Bold="false" />
                <ItemTemplate>
                    <%#Eval("name")%>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="路径">
                <HeaderStyle Width="160px" Font-Bold="true" />
                <ItemStyle Font-Bold="false" />
                <ItemTemplate>
                    <%#Eval("path")%>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="大小">
                <HeaderStyle Width="60px" Font-Bold="true" />
                <ItemStyle Font-Bold="false" />
                <ItemTemplate>
                    <%#Eval("size")%>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</asp:Content>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.Title = WebSettingManager.WebSetting.BaseSetting.title + " - " + WebSettingManager.WebSetting.BaseSetting.subTitle;
            this.lblTitle.Text = WebSettingManager.WebSetting.BaseSetting.title;
            this.lblSubTitle.Text = WebSettingManager.WebSetting.BaseSetting.subTitle;
            this.lblUrl.Text = WebSettingManager.WebSetting.BaseSetting.url;

            this.gvFileUploadSetting.DataSource = WebSettingManager.WebSetting.FileUploadSetting;
            this.gvFileUploadSetting.DataBind();
        }

  运行网站,我们可以看到如下界面,说明我们的配置节点是可用的:

我们可以休息了,哈哈,附上源代码:http://files.cnblogs.com/youring2/SampleWebConfigSection.rar

另外,通过实现System.Configuration.IConfigurationSectionHandler接口来实现自定义配置节点感兴趣的朋友可以点击这里

再附上MSDN上面关于两种实现方法的地址:

http://msdn.microsoft.com/zh-cn/library/2tw134k3(v=VS.100).aspx

http://msdn.microsoft.com/zh-cn/library/ms228056.aspx

我们可以真的休息了,如果你觉得这篇文章还不错,点击一下推荐链接也不费劲,却可以给我很大鼓励,谢谢您的关注!

-------------------------------------------------

ps.补充一点Configuration自定义节点结构:

  • ConfigurationSection:对应整个自定义节点Xml的最外层节点
  • ConfigurationElement:Section节点下的一个子节点,不包含集合
  • ConfigurationElementCollection:对应Element集合

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 关于.NET邮件的收发问题总结(带附件)

    最近因为项目需要,研究了一下邮件的发送和接收,发现现在这方面的问题很多.虽然网上这方面的资料很多,但是真正应用起来 仍然会发现不少问题,而且很多...

    跟着阿笨一起玩NET
  • Orleans 知多少 | 2. 核心概念一览

    上面已经提到,Grain是Virtual Actor的具体表现。那如何理解Grain呢。

    圣杰
  • .NET Core 使用 K8S ConfigMap的正确姿势

    ASP.NET Core默认的配置文件定义在appsetings.json和appsettings.{Environment}.json文件中。 这里面有一个...

    圣杰
  • WPF自学入门(三)WPF路由事件之内置路由事件

    有没有想过在.NET中已经有了事件机制,为什么在WPF中不直接使用.NET事件要加入路由事件来取代事件呢?最直观的原因就是典型的WPF应用程序使用...

    黄昏前黎明后
  • 关于.net中获取图像缩略图的函数GetThumbnailImage的一些认识。

      在很多图像软件中,打开一幅图像的时候都会显示其缩略图,在看图软件中这样的需求更为常见。如何快速的获取缩略图的信息并提供给用户查看,是个值得研究的问题。在我所...

    用户1138785
  • ASP.NET Core 3.0 迁移避坑指南

    .NET Core 3.0将会在 .NET Conf 大会上正式发布,截止今日发布了9个预览版,改动也是不少,由于没有持续关注,今天将前面开源的动态WebApi...

    晓晨
  • 解决WebClient或HttpWebRequest首次连接缓慢问题

    【开发语言】C#, 理论上VB.NET等依赖.NET Framework框架的语言均受此影响

    冰封一夏
  • asp.net 建多个项目实现三层的实例——读取一张表中的记录条数

      学习asp.net两周,通过学习发现,.net和php之间的区别还是蛮大的,比php要复杂一些,开始学习的有些吃力,后来跟着传智播客里的老师学习,渐渐的学到...

    CherishTheYouth
  • 使用DB4o做一个.Net版的website(一)环境

    一个机缘巧合之下,知道了DB4o这个数据库引擎,下载查看之后,被其方便、高效、以及便捷的管理方式锁折服。

    Isaac Zhang
  • 《CLR via C#》Part1之Chapter3 共享程序集和强命名程序集(二)

    CLR支持两种程序集:弱命名程序集(weakly named assembly)和强命名程序集(strongly named assembly).

    Isaac Zhang

扫码关注云+社区

领取腾讯云代金券