ConfigurationSettings类解析

系统 1829 0

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 16.5pt; HEIGHT: 16.5pt" alt="" type="#_x0000_t75"><imagedata o:href="http://bbs.fsll.cn:8090/Images/topicface/face1.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image001.gif"></imagedata></shape>

.Net Framework 源码分析

.Net Framework 的源码是微软编程大师们智慧的结晶,是我们开发人员梦寐以求的知识宝藏。

挖掘这座宝藏是我们快速提升自身编程思想水平的重要途径。

下面是我研究分析 .Net Framework 一部分代码后的一点心得,共享出来,希望对大家有所帮助,当然,分析不对的地方,还望指正,不胜感激。

System.Configuration.ConfigurationSettings

相信大家对这个类都不陌生吧。 ConfigurationSettings 类重要的方法是 ( 在我下面的分析中,方法也包括属性 )

  • AppSettings 属性 用于获取 元素配置节中的配置设置。

  • GetConfig 方法 返回用户定义的配置节的配置设置。

在我们的项目开发中,我们经常通过 ConfigurationSettings.AppSettings["myKey"] 的方法 来获取 web.config 配置项上 appSettings 的配置值。调用这个 ConfigurationSettings.AppSettings["myKey"] 索引器我们就可以获取到 web.cofing 配置项 appSettings 的配置值,这太方便了。如果要我们设计一个这样的功能的时候,我们会有什么想法呢。 我的想法大概的是这样的:

1. 加载 web.config 配置文件的内容

2. 分析 web.config 配置文件配置项 appSettings 节点的内容,并加载到配置项管理类中。

3. 配置项管理类中应该有一个索引器,方便外部系统访问。

让我们来分析大师们是如何实现这个类的。看看大师级人物的代码和设计思路有何高明之处。

//ConfigurationSettings 类的定义

public sealed class ConfigurationSettings

{

}

C# 关键字 sealed 表明此类是不能被继承的。

// 静态构造函数

static ConfigurationSettings()

{

_initState = InitState.NotStarted;

_initLock = new object();

}

一个类最先运行的代码段就是静态构造函数,并且对于整个程序域而言静态构造函数只运行一次。
C#
关键字 static 加上类名称的方法函数就是静态构造函数。
对于一个类来说,只能有一个静态构造函数。
静态构造函数的作用主要是初始化静态变量。
C# 关键字 static 约束的类方法里面的代码都只能调用 静态变量或者静态方法 , 静态属性等。

静态方法: C# 关键字 static 约束的方法就是静态方法 ( 有些教材可能会称为类方法 ) ,里面的代码都只能调用 静态变量或者静态方法 , 静态属性等。

// 静态变量的定义代码

private static object _initLock;

C# 关键字 static 表明此变量为静态变量。

// 构造函数

private ConfigurationSettings()

{

}

发现上面的构造函数跟我们平时所写的类的构造函数有什么不同吗?
对了,就是访问权限的约束关键字 private  ,平时构造函数的约束关键字都是 public
那么将构造函数访问权限设置为 private 有什么目的呢?

1. 防止别人的代码通过 new 操作生成对象实例。

如: System.Configuration.ConfigurationSettings config = new System.Configuration.ConfigurationSettings();

你会发现上面的代码编译不通过,原因就是访问了 private 的构造函数,当然编译不通过啦!

2. 保证一个类仅有一个实例。

这里就是设计模式中的 Singleton 单件模式了,设置构造函数的访问权限为 private 是实现 Singleton 模式的前提

//AppSettings 静态只读属性

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;

}

}

通过上面的代码我们可以知道,此属性为静态只读属性 (static 关键字,只有 get 操作,而没有 set 操作 )
因为 NameValueCollection 类定义了索引访问器,所以平时我们的代码都是这样写的 ConfigurationSettings.AppSettings["myKey"]
,对于 ["myKey"] 这种使用 [] 号访问的索引器,我们下面分析 NameValueCollection 类时再说明索引器。

ReadOnlyNameValueCollection config = (ReadOnlyNameValueCollection) GetConfig(" appSettings ");
注意到参数的值是 appSettings 了吗?
是不是跟我们 web.config 里面的 appSettings 的配置节点项有关联呢?他们有什么关系吗?我们往下看。
这段代码调用了 ConfigurationSettings 类的另外一个静态方法,代码如下:

public static object GetConfig(string sectionName) // 当然这时 sectionName == "appSettings"

{

if ((sectionName == null) || (sectionName.Length == 0))

// 判断 string 的值是不是为 Empty 时,应该用 sectionName.Length == 0  来判断

{

return null;

}

if (_initState < InitState.Usable)

{

EnsureConfigurationSystem();

}

if (_initError != null)

{

throw _initError;

}

return _configSystem.GetConfig(sectionName);

}



代码段:

if (_initState < InitState.Usable)

{

EnsureConfigurationSystem();

}

InitState 只是一个私有的枚举类型 enum

private enum InitState

{

NotStarted,

Started,

Usable,

Completed

}

刚才 ConfigurationSettings 类的静态构造函数是设置
initState = InitState.NotStarted;
那么第一次运行时 , 肯定会执行 EnsureConfigurationSystem() 方法了 , 我们接着看看代码的实现

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# 关键字 lock 加锁处理。
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入一个锁定代码,则它将在释放该对象前一直等待(块)。
MSDN 的解释: lock 关键字可将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。
通常,如果要保护实例变量,则 lock(this) ;如果要保护 static 变量(或者如果临界区出现在给定类的静态方法中),则 lock(typeOf (class))

<shape id="_x0000_i1026" style="WIDTH: 9.75pt; HEIGHT: 11.25pt" alt="" type="#_x0000_t75"><imagedata o:href="http://bbs.fsll.cn:8090/Images/list/ip.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image002.gif"></imagedata></shape>2007-7-24 13:57:32

陈英豪

<shape id="_x0000_i1027" style="WIDTH: 24pt; HEIGHT: 24pt" alt="" type="#_x0000_t75"><imagedata o:href="http://bbs.fsll.cn:8090/Images/face/image52.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image003.gif"></imagedata></shape>
<shape id="_x0000_i1028" style="WIDTH: 82.5pt; HEIGHT: 7.5pt" alt="" type="#_x0000_t75"><imagedata o:href="http://bbs.fsll.cn:8090/Images/star/level10.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image004.gif"></imagedata></shape>
等级:版主
文章: 17
积分: 19
注册: 2007-7-2

<shape id="_x0000_i1029" style="WIDTH: 45pt; HEIGHT: 13.5pt" alt="给2AE6E5308869449895CF7EDAAB814568发送一个短消息" type="#_x0000_t75" o:button="t" target="_blank" href="http://bbs.fsll.cn:8090/smsWrite.aspx?touser=2AE6E5308869449895CF7EDAAB814568"><imagedata o:href="http://bbs.fsll.cn:8090/Images/list/message.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image005.gif"></imagedata></shape> <shape id="_x0000_i1030" style="WIDTH: 36pt; HEIGHT: 13.5pt" alt="把2AE6E5308869449895CF7EDAAB814568加入好友" type="#_x0000_t75" o:button="t" target="_blank" href="http://bbs.fsll.cn:8090/listFriends.aspx?action=add&amp;myFriend=2AE6E5308869449895CF7EDAAB814568"><imagedata o:href="http://bbs.fsll.cn:8090/Images/list/friend.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image006.gif"></imagedata></shape> <shape id="_x0000_i1031" style="WIDTH: 33.75pt; HEIGHT: 13.5pt" alt="查看2AE6E5308869449895CF7EDAAB814568的个人资料" type="#_x0000_t75" o:button="t" target="_blank" href="http://bbs.fsll.cn:8090/dispuser.aspx?id=2AE6E5308869449895CF7EDAAB814568"><imagedata o:href="http://bbs.fsll.cn:8090/Images/list/profile.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image007.gif"></imagedata></shape> <shape id="_x0000_i1032" style="WIDTH: 33.75pt; HEIGHT: 13.5pt" alt="搜索2AE6E5308869449895CF7EDAAB814568的所有贴子" type="#_x0000_t75" o:button="t" target="_blank" href="http://bbs.fsll.cn:8090/search.aspx?keyword=2AE6E5308869449895CF7EDAAB814568"><imagedata o:href="http://bbs.fsll.cn:8090/Images/list/find.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image008.gif"></imagedata></shape> <shape id="_x0000_i1033" style="WIDTH: 33.75pt; HEIGHT: 13.5pt" alt="回复这个贴子" type="#_x0000_t75" o:button="t" href="http://bbs.fsll.cn:8090/post.aspx?action=re&amp;boardid=200&amp;tieid=1082"><imagedata o:href="http://bbs.fsll.cn:8090/Images/list/reply_a.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image009.gif"></imagedata></shape>

2

<shape id="_x0000_i1034" style="WIDTH: 16.5pt; HEIGHT: 16.5pt" alt="" type="#_x0000_t75"><imagedata o:href="http://bbs.fsll.cn:8090/Images/topicface/face1.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image001.gif"></imagedata></shape>

_configSystem = new DefaultConfigurationSystem();

private static IConfigurationSystem _configSystem;

_configSystem 是一个接口变量。
先看看接口 IConfigurationSystem 定义

public interface IConfigurationSystem

{

// Methods

object GetConfig(string configKey);

void Init();

}

接着我们跟踪实现了 IConfigurationSystem 接口的 DefaultConfigurationSystem 类看看
类的定义:

internal class DefaultConfigurationSystem : IConfigurationSystem

{

}

C# 关键字 internal 表明此类只能被当前的 dll 里面的类使用。
顺便提一提 protected internal 这样的二个关键字的约束。它表明这个只能被当前 dll 里面的类使用或者不是当前 dll 里面的子类使用,记得是 或者 的关系
我们还是先从这个类的构造函数分析开始 :

internal DefaultConfigurationSystem()

{

}

这里的构造函数使用 internal ,并不是像 ConfigurationSettings 类构造函数的 private
它的访问权限比 ConfigurationSettings 的类的松一点,允许当前 dll 里面的类可以通过 new 操作来生成多个 DefaultConfigurationSystem 实例。
所以这里才有上面的代码 :
_configSystem = new DefaultConfigurationSystem();
的代码调用。
重要方法 GetConfig 的部分关键代码内容:

object IConfigurationSystem.GetConfig(string configKey) // 当然这里还是 configKey == "appSettings"

{

if (!this._isAppConfigInited)

{

this.EnsureInit(configKey);

}

ConfigurationRecord record = null;

if (record != null)

{

return record.GetConfig(configKey);

}

return null;

}

接下来我们就要分析 EnsureInit 方法。

private void EnsureInit(string configKey)

{

try

{

ConfigurationRecord record = new ConfigurationRecord();

bool flag2 = record.Load(this._machineFilename);

// 加载配置文件信息,这里是加载 machine.config 的信息,并不是 web.config 的信息

this._machineConfig = record;

///.... 省略

}

catch (Exception exception)

{

this._initError = exception;

background: #cccccc; margin:

分享到:
评论
wapysun
  • 浏览: 4877556 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最新评论

ConfigurationSettings类解析


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论