在web.config和app.config文件中增加自定义配置节点的方法

有经验的开发人员都知道在开发.NET应用时可以利用配置文件保存一些常用并且有可能变化的信息,例如日志文件的保存路径、数据库连接信息等等,这样即使生产环境中的参数信息与开发环境不一致也只需要更改配置文件而不用改动源代码再重新编译,极其方便。并且我们一般还约定,在<appSettings>节点保存应用程序的配置信息,在<connectionStrings>中保存数据库连接字符串信息。

上面的这些方法和约定足以让我们在大部分开发中获得方便,但是在有些情况下有些配置信息可以按组分类存放,如果采用上面的方法不仅不直观,而且读取起来也不是太方便,幸好在.NET里就提供了这样的方法。如果有使用过Log4Net或者Enyim.Caching的朋友,肯定对下面的配置不会陌生:


代码如下:

<sectionGroup name="enyim.com"><section name="memcached"
type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" /></sectionGroup>

或:


代码如下:

<configSections><section name="log4net" type="System.Configuration.IgnoreSectionHandler"/></configSections>

在出现上面配置的配置文件中,我们就会找到名称为"enyim.com"或者"log4net"的节点,尽管它们本不属于config文件的默认节点,但是通过上面的配置之后程序运行并不会报错。这样一来,相关配置信息也可以很好分类保存起来。

在这里我演示一个简单的例子,这个例子来源于我的一个从2006年起就开始开发的自用软件(因为没有美化所以没有免费发布),在这个应用程序的connfig文件中我增加了一些特有的配置,所以新增了一个自己的节点,app.config文件内容如下:


代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>  
   <configSections>      
    <section name="SoftwareSettings" type="ImageAssistant.Configuration.SoftwareSettings, ImageAssistant" />  
   </configSections>  
     <SoftwareSettings>    
       <LoadSettings>      
         <add key="LoadBmp" value="true"/>      
         <add key="LoadJpg" value="true"/>      
         <add key="LoadGif" value="true"/>      
         <add key="LoadPng" value="false"/>    
       </LoadSettings>    
     <PathSettings SavePath="C:\ResizeImages\" SearchSubPath="true"/>  
   </SoftwareSettings>

<appSettings>    
      <add key="LoadBmp" value="true"/>    
      <add key="LoadJpg" value="true"/>    
      <add key="LoadGif" value="true"/>    
      <add key="LoadPng" value="false"/>   
      <add key="IncludeSubPath"  value="true"/> 
   </appSettings>    
</configuration>

在config文件中我们使用<section name="SoftwareSettings" type="ImageAssistant.Configuration.SoftwareSettings, ImageAssistant" />告诉应用程序对于配置文件中的SoftwareSettings节点,其对应的类是ImageAssistant程序集中ImageAssistant.Configuration.SoftwareSettings类,并且在<SoftwareSettings>节点中我们还看到有<LoadSettings>节点和<PathSettings>节点,其中<LoadSettings>是一个节点集合,还包含有多个子节点,为了表示清楚这些关系我们需要添加四个类:SoftwareSettings、LoadSettingsCollection、LoadSettingsElement及PathSettingElement。为了发布方便,我将这四个类的代码放在一个物理文件中,代码如下(注意添加对System.Configuration.dll的引用):


代码如下:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Configuration;

namespace ImageAssistant.Configuration 

    public sealed class LoadSettingsCollection : ConfigurationElementCollection 
    { 
        private IDictionary<string, bool> settings;

protected override ConfigurationElement CreateNewElement() 
        { 
            return new LoadSettingsElement(); 
        }

protected override object GetElementKey(ConfigurationElement element) 
        { 
            LoadSettingsElement ep = (LoadSettingsElement)element;

return ep.Key; 
        }

protected override string ElementName 
        { 
            get 
            { 
                return base.ElementName; 
            } 
        }

public IDictionary<string, bool> Settings 
        { 
            get 
            { 
                if (settings == null) 
                { 
                    settings = new Dictionary<string, bool>(); 
                    foreach (LoadSettingsElement e in this) 
                    { 
                        settings.Add(e.Key, e.Value); 
                    } 
                } 
                return settings; 
            } 
        }

public bool this[string key] 
        { 
            get 
            { 
                bool isLoad = true; 
                if (settings.TryGetValue(key, out isLoad)) 
                { 
                    return isLoad; 
                } 
                else 
                { 
                    throw new ArgumentException("没有对'" + key + "'节点进行配置。"); 
                } 
            } 
        }

}

public class LoadSettingsElement : ConfigurationElement 
    { 
        [ConfigurationProperty("key", IsRequired = true)] 
        public string Key 
        { 
            get { return (string)base["key"]; } 
            set { base["key"] = value; } 
        } 
        [ConfigurationProperty("value", IsRequired = true)] 
        public bool Value 
        { 
            get { return (bool)base["value"]; } 
            set { base["value"] = value; } 
        } 
    }

public class PathSettingElement : ConfigurationElement 
    { 
        /// <summary>  
        ///   
        /// </summary>  
        [ConfigurationProperty("SavePath", IsRequired = true)] 
        public string SavePath 
        { 
            get { return (string)base["SavePath"]; } 
            set { base["SavePath"] = value; } 
        } 
        /// <summary>  
        ///   
        /// </summary>  
        [ConfigurationProperty("SearchSubPath", IsRequired = false, DefaultValue = true)] 
        public bool SearchSubPath 
        { 
            get { return (bool)base["SearchSubPath"]; } 
            set { base["SearchSubPath"] = value; } 
        } 
    }

/// <summary>  
    /// 对应config文件中的  
    /// </summary>  
    public sealed class SoftwareSettings : ConfigurationSection 
    { 
        /// <summary>  
        /// 对应SoftwareSettings节点下的LoadSettings子节点  
        /// </summary>  
        [ConfigurationProperty("LoadSettings", IsRequired = true)] 
        public LoadSettingsCollection LoadSettings 
        { 
            get { return (LoadSettingsCollection)base["LoadSettings"]; } 
        }

/// <summary>  
        /// 对应SoftwareSettings节点下的PathSettings子节点,非必须  
        /// </summary>  
        [ConfigurationProperty("PathSettings", IsRequired = false)] 
        public PathSettingElement PathSetting 
        { 
            get { return (PathSettingElement)base["PathSettings"]; } 
            set { base["PathSettings"] = value; } 
        }


}

在上面的代码中可以看到ConfigurationProperty这个属性,这是表示对应的属性在config文件中的属性名,IsRequired表示是否是必须的属性,还有DefaultValue表示属性的默认值。初次之外,我们还要注意以下关系:
SoftwareSettings:根节点,继承自ConfigurationSection。
LoadSettingsCollection:子节点集合,继承自ConfigurationElementCollection。
LoadSettingsElement:子节点,继承自ConfigurationElement。
PathSettingElement:子节点,继承自ConfigurationElement。
编写了如下代码之后,我们又该如何使用上面的类呢?其实很简单,如下:


代码如下:

class Program 
    { 
        static void Main(string[] args) 
        { 
            SoftwareSettings softSettings = ConfigurationManager.GetSection("SoftwareSettings") as SoftwareSettings;

foreach (string key in softSettings.LoadSettings.Settings.Keys) 
            { 
                Console.WriteLine("{0}={1}", key, softSettings.LoadSettings[key]); 
            } 
            Console.WriteLine("SavePath={0},SearchSubPath={1}", softSettings.PathSetting.SavePath, softSettings.PathSetting.SearchSubPath); 
            Console.ReadLine(); 
        } 
    }

这个程序的运行结果如下:
LoadBmp=True
LoadJpg=True
LoadGif=True
LoadPng=False
SavePath=C:/ResizeImages/,SearchSubPath=True

总结:在上面的config文件中通过<appSettings>也达到了类似的效果,但是通过自定义节点我们可以方便地读取相关的应用程序配置,同时也便于维护。如果在开发过程中遇到本文中类似的情况,不妨采取本文所述的方式。

(0)

相关推荐

  • 解决在Web.config或App.config中添加自定义配置的方法详解

    .Net中的System.Configuration命名空间为我们在web.config或者app.config中自定义配置提供了完美的支持.最近看到一些项目中还在自定义xml文件做程序的配置,所以忍不住写一篇用系统自定义配置的随笔了.如果你已经对自定义配置了如指掌,请忽略这篇文章.言归正传,我们先来看一个最简单的自定义配置 复制代码 代码如下: <?xml version="1.0" encoding="utf-8" ?> <configura

  • Web.config 和 App.config 的区别分析

    web.config是web应用程序的配置文件,为web应用程序提供相关配置.在你开发的web程序中,你可以为每一个文件夹建立一个web.config.app.config是桌面应用程序的配置文件.在vs.net中创建一个桌面应用程序工程并添加了应用程序配置文件时,它会自动命名为<appname>.exe.config,并且自动与你的程序进行关联. 不管是web.config,还是app.config,你都可以使用下面的方法获取appsetting节的值: System.Configurati

  • ASP.NET(C#)应用程序配置文件app.config/web.config的增、删、改操作

    配置文件,对于程序本身来说,就是基础和依据,其本质是一个xml文件,对于配置文件的操作,从.NET 2.0 开始,就非常方便了,提供了 System [.Web] .Configuration 这个管理功能的NameSpace,要使用它,需要添加对 System.configuration.dll的引用. 对于WINFORM程序,使用 System.Configuration.ConfigurationManager: 对于ASP.NET 程序, 使用 System.Web.Configurat

  • 基于动态修改App.Config与web.Config的使用详解

    首先假设你的应用程序配置文件如下: 复制代码 代码如下: <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="name" value="old"/> </appSettings> </configuration> Ok,那么如何在运行时去修改name

  • 在web.config和app.config文件中增加自定义配置节点的方法

    有经验的开发人员都知道在开发.NET应用时可以利用配置文件保存一些常用并且有可能变化的信息,例如日志文件的保存路径.数据库连接信息等等,这样即使生产环境中的参数信息与开发环境不一致也只需要更改配置文件而不用改动源代码再重新编译,极其方便.并且我们一般还约定,在<appSettings>节点保存应用程序的配置信息,在<connectionStrings>中保存数据库连接字符串信息. 上面的这些方法和约定足以让我们在大部分开发中获得方便,但是在有些情况下有些配置信息可以按组分类存放,如

  • vue在App.vue文件中监听路由变化刷新页面操作

    在路由跳转时,会出现页面需要重新刷新一遍才能获取数据加载页面,这时添加一个监听器,如果跳转到页面刷新一次. export default { name: 'App', provide(){ return{ reload:this.reload } }, data(){ return { isRouterAlive:true, } }, //监听器 watch: { // 方法1 '$route' (to, from) { //监听路由是否变化 // console.log(999) if(to.

  • vue-cli4使用全局less文件中的变量配置操作

    目录结构如下: 需求: 在Navgation.vue中使用global.less中的变量 vue-cli3的配置方法如下:传送门 vue-cli4的配置方法如下: 安装 style-resources-loader npm i style-resources-loader -D 在 vue.config.js 中加上如下配置,没有则创建该文件,文件名不能改,如下: // vue.config.js const path = require('path') module.exports = { l

  • vue项目中在外部js文件中直接调用vue实例的方法比如说this

    一般我们都是在main.js中引入vue,然后在vue文件中直接使用this(this指向的是vue实例),但是在实际开发中,我们往往会引入外部的js文件使用this,这个this就会指向window,并不是我们期待的vue实例,那么就需要重新引入vue文件(import Vue from 'vue'),这样很麻烦.在目前项目中我使用的方法是mian.js导出vue实例,然后在需要使用的js中引入. 步骤一:main.js导出vue实例 var vue = new Vue({ el: '#app

  • Android实现在xml文件中引用自定义View的方法分析

    本文实例讲述了Android实现在xml文件中引用自定义View的方法.分享给大家供大家参考,具体如下: 在xml中引用自定义view 方法一: <view class="com.test.copytext.CopyText" android:layout_width="fill_parent" android:layout_height="wrap_content" /> 方法二: <view class="com.

  • Python统计文件中去重后uuid个数的方法

    本文实例讲述了Python统计文件中去重后uuid个数的方法.分享给大家供大家参考.具体如下: 利用正则表达式按行获取日志文件中的的uuid,并且统计这些uuid的去重个数(去重利用set) import re pattern=re.compile(r'&uuid=.*&') uuidset=set() with open('request.log.2015-05-26','rt') as f: for line in f: all=pattern.findall(line) if len

  • Python 实现引用其他.py文件中的类和类的方法

    #HelloWorld是文件名称,Hello是类 from HelloWorld import Hello 调用,Hello类的方法: >>> h = Hello() >>> h.hello() Hello, world #输出结果 #>>> Hello().hello() #Hello, world 附:HelloWorld.py文件内容 以上这篇Python 实现引用其他.py文件中的类和类的方法就是小编分享给大家的全部内容了,希望能给大家一个参考

  • C++从txt文件中读取二维的数组方法

    此文章用来做笔记, 从MATLAB中保存的二维数组1500*2的数据到txt文件中,格式化保存方式如下: MATLAB代码: fid=fopen('data.txt','wt'); for i=1:1500 fprintf(fid,'%.3f\t%.3f\n',r(i,:)); end fclose(fid); 其中r是1500*2的矩阵 在C++中读取到程序中,使用文件流: #include<iostream> #include<fstream> #include<type

  • 使用python对多个txt文件中的数据进行筛选的方法

    一.问题描述 筛选出多个txt文件中需要的数据 二.数据准备 这是我自己建立的要处理的文件,里面是随意写的一些数字和字母 三.程序编写 import os def eachFile(filepath): pathDir =os.listdir(filepath) #遍历文件夹中的text return pathDir def readfile(name): fopen=open(name,'r') for lines in fopen.readlines(): #按行读取text中的内容 lin

随机推荐