`

ConfigurationSettings类解析

阅读更多

<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:

分享到:
评论

相关推荐

    mybatis3.x源码深度解析与最佳实践.pdf

    XMLConfigBuilder.parseConfiguration 方法是 MyBatis 中的核心方法之一,该方法负责解析 MyBatis 的配置文件,包括属性解析、加载 settings 节点、加载自定义 VFS、解析类型别名、加载插件、加载对象工厂、创建对象...

    Maven3实战笔记05仓库依赖解析与插件解析

    远程仓库可以通过在`pom.xml`或全局设置文件`settings.xml`中配置。例如: ```xml &lt;id&gt;jboss &lt;url&gt;http://repository.jboss.com/maven2/&lt;/url&gt; &lt;enabled&gt;true &lt;enabled&gt;false &lt;layout&gt;default `...

    MyBatis源码分析.pdf

    MyBatis会将&lt;settings&gt;节点解析到Settings对象中,然后将其设置到Configuration对象中。 3. 映射文件解析过程 MyBatis的映射文件解析过程是MyBatis的核心组件之一,负责解析MyBatis的映射文件,并将其转换为...

    比较好用的一个C#FTP类,源码

    int FTPRemotePort = Convert.ToInt32(ConfigurationSettings.AppSettings["FTPRemotePort"]); string FTPUser = ConfigurationSettings.AppSettings["FTPUser"]; string FTPPassword = ConfigurationSettings....

    asp.net小实例解析

    SqlConnection myConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString"]); SqlCommand myCommand = new SqlCommand("ShoppingCartAddItem", myConnection); // 指定命令...

    C#学习心得

    值得注意的是,在.NET Framework 4.0及更高版本中,建议使用`ConfigurationManager.ConnectionStrings`方法来替代`ConfigurationSettings.AppSettings`,因为后者已被标记为过时。 此外,代码中还展示了一种通过...

    hibernate源码分析一[启动过程]

    `Settings`类负责存储由`Configuration`类解析出来的系统配置信息。它将诸如数据库连接提供者(`ConnectionProvider`)、事物处理方式、缓存策略等转换为Java对象,便于后续使用。 #### Configuration类 `...

    tnsping命令解析

    - `service_name` 是指要使用tnsping测试的远程数据库服务名称,也就是在Oracle配置和移植工具Net Configuration Assistant中创建的网络服务名。 - `[n]` 是可选参数,表示tnsping命令重复执行的次数,默认情况下只...

    Asp.net三层架构开发另类实例解析

    _conn = new SqlConnection(ConfigurationSettings.AppSettings["connectionString"]); } public void OpenConnection() { if (_conn.State != ConnectionState.Open) _conn.Open(); } // 其他数据库...

    myBatis执行流程全解析1

    - `XMLConfigBuilder`解析`mybatis-config.xml`,构建`Configuration`对象,这个对象包含了myBatis的所有配置信息。 - `XMLMapperBuilder`处理`mapper.xml`文件,根据`mapper`元素构建`MapperRegistry`,并为每个`...

    .net发送邮件的方法

    string strAccount = ConfigurationSettings.AppSettings["EmailAccount"].Trim(); // SMTP账户名 string strPwd = ConfigurationSettings.AppSettings["EmailPwd"].Trim(); // SMTP密码 string strFrom = ...

    2007年3月Y2笔试.doc

    在 ASP.NET 中,通过 `System.Configuration.ConfigurationSettings.AppSettings` 方法来获取配置文件中的值。 #### 正确答案解析 - 正确答案是 **a)string strDSN = System.Configuration.ConfigurationSettings....

    C#SQL数据库操作类[文].pdf

    在类的构造函数中,通过`ConfigurationSettings.AppSettings["ConnStr"]`获取配置文件中的连接字符串,这允许开发者在不修改代码的情况下更改数据库连接信息。 - `public SqlConnection ReturnConn()`: 创建并打开一...

    C#实现网页中上传文件

    这可以通过`System.Configuration.ConfigurationSettings.AppSettings`属性来实现,它提供了一种方便的方式访问应用程序的配置信息。 #### 5. 类和方法设计 为了组织和封装代码,C#提供了类和方法的概念。在给定的...

    .net 实现支付宝

    t1 = ConfigurationSettings.AppSettings["interface"]; t2 = ConfigurationSettings.AppSettings["account"]; t3 = ConfigurationSettings.AppSettings["password"]; ``` 其中,`t1`代表支付宝接口的URL,`t2`是...

    DbHelper.txt

    protected static string connectionString = ConfigurationSettings.AppSettings["Sql"]; ``` 这里通过`.NET`框架中的`ConfigurationSettings.AppSettings`来获取数据库连接字符串。这种做法的优点是将敏感信息...

    数据库操纵经典类(C#)

    该字段存储了数据库连接字符串,通过`ConfigurationSettings.AppSettings["ConnectionString"]`获取。此字符串通常包含服务器地址、数据库名称、用户名和密码等信息,用于建立与SQL Server数据库的连接。 ### 构造...

    C#配置文件概述[文].pdf

    开发者可以通过`ConfigurationSettings.AppSettings`静态属性来访问这些设置,例如: ```csharp string connectionString = ConfigurationSettings.AppSettings["connectionstring"]; ``` 除了预定义的配置节,C#...

    ACCP教员面试题目

    通过`ConfigurationSettings.AppSettings`可以访问配置项,例如`GetQuery = ConfigurationSettings.AppSettings["MySQLQuery"];` 8. **ADO.NET操作**:`ExecuteNonQuery()`用于执行非查询操作(如INSERT、UPDATE、...

    Hibernate源代码分析(一)

    Configuration 类是 Hibernate 框架的核心类之一,负责管理 sessionFactory 和 connection Providers。通过对 Configuration 类的分析,我们可以了解到 sessionFactory 的创建过程和 ConnectionProvider 的实现机制...

Global site tag (gtag.js) - Google Analytics