剛剛學習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)) 這句不應該這樣寫,但又沒找到好的方法,所以就這樣寫了。