• 在C#类库中使用App.config文件自定义配置


      做项目时,经常需要在自己设计的类库中使用很多用户配置。虽然在应用程序的App.config和Web应用程序web.config这样的文件里配置也能满足需求,但这样做不仅会让主配置文件的内容变得多、杂,还会让模块依赖主程序的配置文件。

      我们知道在VS中,可以在类库项目里添加一种叫做“应用程序配置文件”的文件,这是标准的.NET配置文件,模板自带“configuration”元素,编辑时还会有智能提示。但是怎么在程序代码中使用写在App.config里的配置呢?近日在网上搜了一通,却一无所获。于是只好自已动手!

      我以前做的一个项目里,用到过类型的实现方式。可以获取在类库App.config文件中“appSettings”和“conectionStrings”节添加的自定义配置,但是不能自定义配置节。从MSDN上了解到,要想在配置文件中自定义配置节,需要实现一个自定义的ConfigurationSection。两下结合起来,想在类库中用App.config彻底自定义配置的需求就可以实现了。

      现在分享出来,希望对看到这篇文章的朋友有所帮助。

      第一步:创建项目和类库:

      新建一个Windows控制台应用程序“MyDemo”,然后再新建一个C#类库“MyDemo.Config”,并在MyDemo中添加对MyDemo.Config的引用。

      第二步:添加引用,新建配置文件:

      在MyDemo.Config中先删除除System之外的所有引用,然后添加对System.Configuration库的引用,并新建一个配置文件App.config。


     

      第三步:在MyDemo.Config里面添加一个静态类“ConfigManager”,代码里这样写:

    View Code
    using System;
    using System.Configuration;
    
    namespace MyDemo.Config
    {
        public static class ConfigManager
        {
            readonly static bool _Error;
    
            static Configuration _AppConfig;
    
            static ConfigManager()
            {
                string dllPath = string.Format(
                    "{0}\\{1}.dll", AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory, "MyDemo.Config");
    
                try
                {
                    _AppConfig = ConfigurationManager.OpenExeConfiguration(dllPath);
                }
                catch(ConfigurationErrorsException)
                {
                    _Error = true;
                }
            }
    
            public static KeyValueConfigurationCollection AppSettings
            {
                get 
                {
                    if (_Error) return null;
                    return _AppConfig.AppSettings.Settings;
                }
            }
    
            public static ConnectionStringSettingsCollection ConnectionStrings
            {
                get
                {
                    if (_Error) return null;
                    return _AppConfig.ConnectionStrings.ConnectionStrings;
                }
            }
        }
    }

      通过AppDomain.CurrentDomain.BaseDirectory和稳定的类库名称,来获取实际运行中该dll文件的具体物理路径,然后通过ConfigurationManager的OpenExeConfiguration方法就能获取到相应的dll.config文件中的配置。

      为了保险起见,我增加了一个_Error字段,在静态构造器中使用了try语句,这样能保证程序的顺序运行!

      通过这个ConfigManager,可以直接获取在App.config中添加的appSeetings和connectionStrings的配置。

      第四步:添加对自定义的配置节的支持

      要自定义配置节,需要实现ConfigurationSection。这个其实MSDN上就有很好的例子,我这里做一个简单的实现,比如我要增加这样的配置:

    <smtp host="smtp.163.com" mail="abc@163.com" pass="123456"></smtp>

      我们来新建一个SmtpSection,继承自ConfigurationSection。重写基类的IsReadOnly()方法,表示这些配置是只读的。

      然后我们添加几个只读的属性:Host(string)、Mail(string)、Password(string)、Port(int);get访问器的实现很特殊,要用this["自定义配置节的attribute名称"]这种方法,还要转换成相应属性的具体类型。所有将在配置中出现的属性,都要加上ConfigurationProperty标记。

      来看具体的实现:

    View Code
    using System;
    using System.Configuration;
    
    namespace MyDemo.Config
    {
        public class SmtpSection : ConfigurationSection
        {
            public override bool IsReadOnly()
            {
                return true;
            }
    
            [ConfigurationProperty("host", IsRequired = true)]
            public string Host
            {
                get { return this["host"] as string; }
            }
    
            [ConfigurationProperty("mail", IsRequired = true)]
            //[RegexStringValidator(可以在这里用正则验证配置文件中的值是否正确)]
            public string Mail
            {
                get { return this["mail"] as string; }
            }
    
            [ConfigurationProperty("pass", IsRequired = true)]
            public string Password
            {
                get { return this["pass"] as string; }
            }
    
            [ConfigurationProperty("port", IsRequired = false, DefaultValue = 25)]
            [IntegerValidator(MaxValue = 65535, MinValue = 1)]
            public int Port
            {
                get { return (int)this["port"]; }
            }
        }
    }

      可以看到,在声明属性的ConfigurationProperty标记时,不但可以指定此属性将在配置文件中出现的的名称,还可以指定默认值、是否必须属性等。字符串还可以使用RegexStringValidator标记来验证用户输入的配置是否合法;数字则可以用IntegerValidator来规定用户输入的数字范围。最贴心的是这些合法性的验证,都是在编译时进行的,而不是在程序运行时。

      第五步:在App.Config中添加自定义配置节

      新增一个configSections节,在下面添加自定义的section,nam的值是下面的xml元素的开始和结束标记,type的值的格式是这样的“自定义配置节类型的完全名称(包括命名空间), 命名空间”。这里增加一个appSetting和connectionString以便稍后测试。

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="smtp" type="MyDemo.Config.SmtpSection, MyDemo.Config" />
      </configSections>
      <smtp host="smtp.163.com" mail="abc@163.com" pass="123456"></smtp>
      <appSettings>
        <add key="domain" value="dream.net" />
      </appSettings>
      <connectionStrings>
        <add name="default" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|NORTHWND.MDF;Integrated Security=True;Connect Timeout=30" />
      </connectionStrings>
    </configuration>

      第六步:修改ConfigManager,添加获取自定义配置节smtp的方法

      给ConfigManager类增加一个方法,为了能最大限度的重用这个方法,我把方法写成了泛型方法! GetSection<T>(string name);

        public static T GetSection<T>(string name) where T : ConfigurationSection
        {
            if (_Error) return null;
            return _AppConfig.GetSection(name) as T;
        }

      第七步:测试

      要想使这个配置起使用,前提是App.config文件必须以“dll名称.dll.config”的文件名存在应用程序的执行目录中。生成类库的时候,在类库的输出目录会自动生成这个配置文件,但是每次更新配置文件都要把配置文件复制一遍很麻烦。解决办法就是,把App.config改名。比如上面提到的MyDemo.Config中的App.config就可以改成“MyDemo.Config.dll.config”,然后设置属性“复制到输出目录”为“较新则复制”。这样,每次修改配置文件后,只要重新生成,配置文件就会被自动复制到应用程序的执行目录中。

      解决了这个问题,我们在MyDemo中写一段代码测试一下,因为ConfigManager的一些属性和方法的返回值的类型位于System.Configuration命名空间,所以,要使用它必须在程序中也添加对System.Configuration的引用。当然,你也可以改变一下获取appSettings和connectionStrings的方式,直接返回配置的值,而不是配置集合!

    using MyDemo.Config;    
    class Program { static void Main(string[] args) { Console.WriteLine(ConfigManager.AppSettings["domain"].Value); Console.WriteLine(ConfigManager.ConnectionStrings["default"].ConnectionString); var smtp = ConfigManager.GetSection<MyDemo.Config.SmtpSection>("smtp"); Console.WriteLine(smtp.Host); Console.WriteLine(smtp.Mail); Console.WriteLine(smtp.Password); Console.WriteLine(smtp.Port); Console.Read(); } }

      运行结果:

      

       通过结果,可以确定配置在config里面的设置都已经被顺利的读出来了;这是ConfigurationSection的实现,另外,如果要实现的配置具有复杂数据结构,还要根据需要实现ConfigurationElement,具体实现请参考MSDN的例子 http://msdn.microsoft.com/zh-cn/library/2tw134k3(v=vs.100).aspx

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    PS:可以对例子的ConfigManager做一些改造,使之成为项目配置存取模块(Configuration是支持读写的)。另外,对于一些不想这么麻烦的懒人,我推荐一款免费的VS插件,叫“Configuration Section Designer”,安装插件后会安装一个配置节的设计模板,允许你像设计UML图一样设计你的配置,插件会帮你自动生成具体的实现,非常的实用。

    Demo下载

    查看有关Configuration Section Designer的信息

  • 相关阅读:
    BPM实例方案分享:表单子表自动填入数据
    H3 BPM循环子表相关方法介绍
    H3 BPM前后台交互方法介绍
    Web Service Adapter简介:
    H3 BPM钉钉接入配置
    H3 BPM 跨平台表单发起详解
    H3 BPM门户操作说明及实例介绍
    H3 BPM报销流程开发示例
    Photon Cloud Networking: OnPhotonSerializeView Not Firing
    unity 事件顺序及功能说明
  • 原文地址:https://www.cnblogs.com/shalves/p/use_appconfig_on_csharp_library.html
Copyright © 2020-2023  润新知