.Net Framework
的源碼是微軟編程大師們智慧的結(jié)晶,是我們開(kāi)發(fā)人員夢(mèng)寐以求的知識(shí)寶藏。
挖掘這座寶藏是我們快速提升自身編程思想水平的重要途徑。
下面是我研究分析
.Net Framework
一部分代碼后的一點(diǎn)心得,共享出來(lái),希望對(duì)大家有所幫助,當(dāng)然,分析不對(duì)的地方,還望指正,不勝感激。
System.Configuration.ConfigurationSettings
類(lèi)
相信大家對(duì)這個(gè)類(lèi)都不陌生吧。
ConfigurationSettings
類(lèi)重要的方法是
(
在我下面的分析中,方法也包括屬性
)
-
AppSettings
屬性
用于獲取
元素配置節(jié)中的配置設(shè)置。
-
GetConfig
方法
返回用戶(hù)定義的配置節(jié)的配置設(shè)置。
在我們的項(xiàng)目開(kāi)發(fā)中,我們經(jīng)常通過(guò)
ConfigurationSettings.AppSettings["myKey"]
的方法
來(lái)獲取
web.config
配置項(xiàng)上
appSettings
的配置值。調(diào)用這個(gè)
ConfigurationSettings.AppSettings["myKey"]
索引器我們就可以獲取到
web.cofing
配置項(xiàng)
appSettings
的配置值,這太方便了。如果要我們?cè)O(shè)計(jì)一個(gè)這樣的功能的時(shí)候,我們會(huì)有什么想法呢。
我的想法大概的是這樣的:
1.
加載
web.config
配置文件的內(nèi)容
2.
分析
web.config
配置文件配置項(xiàng)
appSettings
節(jié)點(diǎn)的內(nèi)容,并加載到配置項(xiàng)管理類(lèi)中。
3.
配置項(xiàng)管理類(lèi)中應(yīng)該有一個(gè)索引器,方便外部系統(tǒng)訪(fǎng)問(wèn)。
讓我們來(lái)分析大師們是如何實(shí)現(xiàn)這個(gè)類(lèi)的。看看大師級(jí)人物的代碼和設(shè)計(jì)思路有何高明之處。
//ConfigurationSettings
類(lèi)的定義
public
sealed
class ConfigurationSettings
{
}
C#
關(guān)鍵字
sealed
表明此類(lèi)是不能被繼承的。
//
靜態(tài)構(gòu)造函數(shù)
static
ConfigurationSettings()
{
_initState = InitState.NotStarted;
_initLock = new object();
}
一個(gè)類(lèi)最先運(yùn)行的代碼段就是靜態(tài)構(gòu)造函數(shù),并且對(duì)于整個(gè)程序域而言靜態(tài)構(gòu)造函數(shù)只運(yùn)行一次。
C#
關(guān)鍵字
static
加上類(lèi)名稱(chēng)的方法函數(shù)就是靜態(tài)構(gòu)造函數(shù)。
對(duì)于一個(gè)類(lèi)來(lái)說(shuō),只能有一個(gè)靜態(tài)構(gòu)造函數(shù)。
靜態(tài)構(gòu)造函數(shù)的作用主要是初始化靜態(tài)變量。
以
C#
關(guān)鍵字
static
約束的類(lèi)方法里面的代碼都只能調(diào)用
靜態(tài)變量或者靜態(tài)方法
,
靜態(tài)屬性等。
靜態(tài)方法:
C#
關(guān)鍵字
static
約束的方法就是靜態(tài)方法
(
有些教材可能會(huì)稱(chēng)為類(lèi)方法
)
,里面的代碼都只能調(diào)用
靜態(tài)變量或者靜態(tài)方法
,
靜態(tài)屬性等。
//
靜態(tài)變量的定義代碼
private
static
object _initLock;
C#
關(guān)鍵字
static
表明此變量為靜態(tài)變量。
//
構(gòu)造函數(shù)
private
ConfigurationSettings()
{
}
發(fā)現(xiàn)上面的構(gòu)造函數(shù)跟我們平時(shí)所寫(xiě)的類(lèi)的構(gòu)造函數(shù)有什么不同嗎?
對(duì)了,就是訪(fǎng)問(wèn)權(quán)限的約束關(guān)鍵字
private
,平時(shí)構(gòu)造函數(shù)的約束關(guān)鍵字都是
public
的
那么將構(gòu)造函數(shù)訪(fǎng)問(wèn)權(quán)限設(shè)置為
private
有什么目的呢?
1.
防止別人的代碼通過(guò)
new
操作生成對(duì)象實(shí)例。
如:
System.Configuration.ConfigurationSettings config = new System.Configuration.ConfigurationSettings();
你會(huì)發(fā)現(xiàn)上面的代碼編譯不通過(guò),原因就是訪(fǎng)問(wèn)了
private
的構(gòu)造函數(shù),當(dāng)然編譯不通過(guò)啦!
2.
保證一個(gè)類(lèi)僅有一個(gè)實(shí)例。
這里就是設(shè)計(jì)模式中的
Singleton
單件模式了,設(shè)置構(gòu)造函數(shù)的訪(fǎng)問(wèn)權(quán)限為
private
是實(shí)現(xiàn)
Singleton
模式的前提
//AppSettings
靜態(tài)只讀屬性
public static NameValueCollection AppSettings
{
get
{
ReadOnlyNameValueCollection config = (ReadOnlyNameValueCollection) GetConfig("
appSettings
");
if (config == null)
{
config = new ReadOnlyNameValueCollection(new
CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture), new
CaseInsensitiveComparer(CultureInfo.InvariantCulture));
config.SetReadOnly();
}
return config;
}
}
通過(guò)上面的代碼我們可以知道,此屬性為靜態(tài)只讀屬性
(static
關(guān)鍵字,只有
get
操作,而沒(méi)有
set
操作
)
因?yàn)?
NameValueCollection
類(lèi)定義了索引訪(fǎng)問(wèn)器,所以平時(shí)我們的代碼都是這樣寫(xiě)的
ConfigurationSettings.AppSettings["myKey"]
,對(duì)于
["myKey"]
這種使用
[]
號(hào)訪(fǎng)問(wèn)的索引器,我們下面分析
NameValueCollection
類(lèi)時(shí)再說(shuō)明索引器。
ReadOnlyNameValueCollection config = (ReadOnlyNameValueCollection) GetConfig("
appSettings
");
注意到參數(shù)的值是
appSettings
了嗎?
是不是跟我們
web.config
里面的
appSettings
的配置節(jié)點(diǎn)項(xiàng)有關(guān)聯(lián)呢?他們有什么關(guān)系嗎?我們往下看。
這段代碼調(diào)用了
ConfigurationSettings
類(lèi)的另外一個(gè)靜態(tài)方法,代碼如下:
public static object GetConfig(string sectionName)
//
當(dāng)然這時(shí)
sectionName
== "appSettings"
{
if ((sectionName == null) || (sectionName.Length == 0))
//
判斷
string
的值是不是為
Empty
時(shí),應(yīng)該用
sectionName.Length == 0
來(lái)判斷
{
return null;
}
if (_initState < InitState.Usable)
{
EnsureConfigurationSystem();
}
if (_initError != null)
{
throw _initError;
}
return _configSystem.GetConfig(sectionName);
}
代碼段:
if (_initState < InitState.Usable)
{
EnsureConfigurationSystem();
}
InitState
只是一個(gè)私有的枚舉類(lèi)型
enum
private
enum
InitState
{
NotStarted,
Started,
Usable,
Completed
}
剛才
ConfigurationSettings
類(lèi)的靜態(tài)構(gòu)造函數(shù)是設(shè)置
initState = InitState.NotStarted;
那么第一次運(yùn)行時(shí)
,
肯定會(huì)執(zhí)行
EnsureConfigurationSystem()
方法了
,
我們接著看看代碼的實(shí)現(xiàn)
private static void EnsureConfigurationSystem()
{
lock
(_initLock)
{
if (_initState < InitState.Usable)
{
_initState = InitState.Started;
try
{
_configSystem = new DefaultConfigurationSystem();
_initState = InitState.Usable;
}
catch (Exception exception)
{
_initError = exception;
_initState = InitState.Completed;
throw;
}
}
}
}
C#
關(guān)鍵字
lock
加鎖處理。
lock
確保當(dāng)一個(gè)線(xiàn)程位于代碼的臨界區(qū)時(shí),另一個(gè)線(xiàn)程不進(jìn)入臨界區(qū)。如果其他線(xiàn)程試圖進(jìn)入一個(gè)鎖定代碼,則它將在釋放該對(duì)象前一直等待(塊)。
MSDN
的解釋?zhuān)?
lock
關(guān)鍵字可將語(yǔ)句塊標(biāo)記為臨界區(qū),方法是獲取給定對(duì)象的互斥鎖,執(zhí)行語(yǔ)句,然后釋放該鎖。
通常,如果要保護(hù)實(shí)例變量,則
lock(this)
;如果要保護(hù)
static
變量(或者如果臨界區(qū)出現(xiàn)在給定類(lèi)的靜態(tài)方法中),則
lock(typeOf (class))
。
|