簡化並統一 ConfigurationManager 的操作

剛剛學習C#,覺得它與Delphi真的很相似,畢竟是同一個老爸創造的東西,所以相似也是十分正常的。
今天學習了使用 ConfigurationManager,這玩意的作用就是管理應用程序的設置了。一般用法就是

setting1 = ConfigurationManager.AppSettings["setting1"].ToString();
setting2 = ConfigurationManager.AppSettings["setting2"].ToString();


......
可以對應讀出app.config中的配置內容,大概就是:

 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="setting1" value="settingvalue1"/>
    <add key="setting2" value="settingvalue2"/>
    ......
  </appSettings>
</configuration>



這個類是個好東西,方便程序員讀取本地設置。但因爲它太方便了,所以我曾經見過一些教程的示範代碼是隨用隨讀取,即是哪個地方需要配置了,就馬上用上面的代碼讀取。我覺得這是十分低效的做法,我喜歡把所有的配置都放到一個基本設置類裏面去的,一次讀出,這樣有效地控制程序模塊間的不統一性以及讀取文件的延時,如這樣:

class BaseAppValueConf
{
 public static string setting1 = "";
  public static string setting2 = "";
  ......
 public static void initMe()
 {
  setting1 = ConfigurationManager.AppSettings["setting1"].ToString();
  setting2 = ConfigurationManager.AppSettings["setting2"].ToString();
  ......
 }
}


 

不知大家有沒有這個感覺,寫這種讀取、寫入配置的工作是一件低技術、重複、不好玩的事、而且費神費力的事。每寫一個配置的名稱就要重複寫它的名字很多次(4次), 如果一個程序有個幾十個設置,那就相當惹人煩,而且很容易錯,所以我這樣去做:

創建一個抽象的基類,把它放在一個公共的文件中,我自己就用 FlexAppSetting.cs,方便其它應用能共享:

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


namespace FlexAppSetting
{

    public abstract class CustomBaseAppValueConf
    {
        private static bool hasKey(string[] ak, string n) 
        {
            for (int i = 0; i < ak.Count(); i++)
            {
                if (ak[i] == n) return true;
            }
            return false;
        }
        
        abstract public void initMe();
        
        protected void _initMe(CustomBaseAppValueConf cbavc)
        {
            Type selfType = cbavc.GetType();
            System.Reflection.FieldInfo [] fis = selfType.GetFields();

            for (int i = 0; i < fis.Count(); i++)
            {
                string[] ak = ConfigurationManager.AppSettings.AllKeys; 
                if (hasKey(ak, fis[i].Name))
                {
                    if (fis[i].FieldType.Name == "Int32")
                    {
                        int v;
                        try
                        {
                            v = Convert.ToInt32(ConfigurationManager.AppSettings[fis[i].Name].ToString());
                        }
                        catch (Exception)
                        {
                            v = 0;
                        }
                        
                        fis[i].SetValue(selfType, v);
                    }
                    else
                    {
                        fis[i].SetValue(selfType, ConfigurationManager.AppSettings[fis[i].Name].ToString());
                    }
                }
            }
        }
    }
}


 

然後在某個應用程序中,當要讀取配置時,只要這樣做就行了。

 

class BaseAppValueConf : CustomBaseAppValueConf
{
 public static string setting1 = "";
  public static string setting2 = "";
  public static int nonSaveSetting = 2;
  ......
 public static void initMe()
 {
  _initMe(this);
  ......
  nonSaveSetting = 5555;
 }
}

 

....
            BaseAppValueConf bavc = new BaseAppValueConf();
            BaseAppValueConf.appPath = System.AppDomain.CurrentDomain.BaseDirectory;
            bavc.initMe();


 

這個CustomBaseAppValueConf 的作用就是對照着程序中的各設置值的名字,自動從app.config中讀取出來,比原來要方便,而且不容易錯,只要在程序中寫一次變量名,在xml中再寫一次就行了。
CustomBaseAppValueConf中用到了C#的反射機制,這是個好東西,與Delphi裏的RTTI十分相似,但比Delphi的要強。
另外,希望各位前輩指正一下程序。總覺得  if (hasKey(ak, fis[i].Name)) 這句不應該這樣寫,但又沒找到好的方法,所以就這樣寫了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章