【sharpedge 】.NET配置檔案解析過程詳解
.NET配置檔案解析過程詳解
在我看來,WEB project的開發與WINFORM的開發最大的區別在於web的執行是在Framework上更高一層框架上執行,即ASP。NET框架,程式設計師在web下的開發可以說是黑盒開發,不是讓你去定義程式入口和執行順序,而是asp.net來呼叫你的各個方法,程式設計師做的一切都是一種受控的舞蹈。就像我們呼叫nunit之類的工具來測試一個dll一樣,nunit是容器,是框架,執行哪個方法是由nunt來決定的。因此,也就有了頁面執行週期各狀態等令剛入門的程式設計師困惑不已的事,其實,究其根源,在於不瞭解容器而去使用容器。對於asp.net框架的學習,我們不妨從配置檔案開始。
對於程式開發者而言,寫配置檔案是經常性的工作,如果你寫了一個xx.config檔案,如果沒有詳盡的註釋,別人恐怕很難讀懂,沒有良好的配置架構,程式也失去了活力。在我看來,.net配置檔案的特點在於反射定義和繼承性。
我們訪問配置檔案時經常覺得配置檔案的結構不太符合我們的需要,我們需要從裡面更方便地獲得自己定義的物件,而不僅僅是key和value,對於自定義配置檔案的著述已有很多,在此不再描述,有興趣的朋友可以訪問http://ly4cn.cnblogs.com/archive/2005/09/06/231245.html。 自定義配置節其實還是在.net配置檔案架構的應用而已,我們先來搞懂配置檔案的結構,弄清楚.net配置檔案的執行方式。下面是machine.config的一部分內容:
<section name="runtime" type="System.Configuration.IgnoreSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowLocation="false" />
<sectionGroup name="system.net">
<section name="authenticationModules" type="System.Net.Configuration.NetAuthenticationModuleHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
sectionGroup>
configSections>
SDK中的定義為:
name="section name"
type="configuration section handler class, assembly"
allowDefinition="Everywhere|MachineOnly|MachineToApplication"
allowLocation="true|false" />
name="section group name"/>
sectionGroup>
我們來看看.net框架內是如何利用這種結構的。反編譯System.dll找到GetConfig方法,在裡面我們發現實際獲取config的工作預設是由實現了IConfigurationSystem的DefaultConfiguationSystem類來實現的。
{
if (!ConfigurationSettings._configurationInitialized)
{
lock (typeof(ConfigurationSettings))
{
if ((ConfigurationSettings._configSystem == null) && !ConfigurationSettings.SetConfigurationSystemInProgress)
{
ConfigurationSettings.SetConfigurationSystem(new DefaultConfigurationSystem());
}
}
}
if (ConfigurationSettings._initError != null)
{
throw ConfigurationSettings._initError;
}
return ConfigurationSettings._configSystem.GetConfig(sectionName);
}
2{
3 // Methods
4 internal DefaultConfigurationSystem();
5 object IConfigurationSystem.GetConfig(string configKey);
6 void IConfigurationSystem.Init();
7
8 // Properties
9 internal static Uri AppConfigPath { get; }
10 internal static string MachineConfigurationFilePath { get; }
11 internal static string MsCorLibDirectory { get; }
12
13 // Fields
14 private ConfigurationRecord _application;
15 private const string ConfigExtension = "config";
16 private const string MachineConfigFilename = "machine.config";
17 private const string MachineConfigSubdirectory = "Config";
18 private const int MaxPathSize = 0x400;
19}
20
事實上所有的配置檔案的分析和獲取都是在ConfiguationRecord裡實現的,作為配置檔案分析的第一步,正如我們經常做的一樣->載入一個配置檔案,這個方法公開為 Load(filename)。DefaultConfiguationSystem的Init()方法中用machine.config建立了一個 ConfiguationRecord物件,並將其作為父物件傳遞給當前程式的ConfiguationRecord物件,當然前提是當前程式有配置檔案,比如myapp.config,然後再載入當前程式的配置檔案,從而實現配置檔案的繼承。
{
lock (this)
{
if (this._application == null)
{
ConfigurationRecord record1 = null;
string text1 = DefaultConfigurationSystem.MachineConfigurationFilePath;
Uri uri1 = DefaultConfigurationSystem.AppConfigPath;
this._application = record1 = new ConfigurationRecord();
bool flag1 = record1.Load(text1);
if (!flag1 || (uri1 == null))
{
return;
}
this._application = new ConfigurationRecord(record1);
this._application.Load(uri1.ToString());
}
}
}
現在我們可以專注於ConfiguationRecord的具體實現了,Load方法中得到一個XmlTextWriter,並執行.ScanFactoriesRecursive和ScanSectionsRecursive方法。
if (reader1 != null)
{
this.ScanFactoriesRecursive(reader1);
if (reader1.Depth == 1)
{
this.ScanSectionsRecursive(reader1, null);
}
return true;
}
ScanFactoriesRecursive方法會呼叫他的一個過載方法來解析
this.CheckRequiredAttribute(text4, "type", reader);
this.VerifySectionName(text3, reader);
string text5 = ConfigurationRecord.TagKey(configKey, text3);
if (this.HaveFactory(text5) != ConfigurationRecord.HaveFactoryEnum.NotFound)
{
objArray1 = new object[] { text3 } ;
throw this.BuildConfigError(SR.GetString("Tag_name_already_defined", objArray1), reader);
}
this.EnsureFactories[text5] = text4;
goto Label_02B6;
ScanSectionsRecursive方法會解析配置檔案裡的section例項,並將其tagkey儲存到Hashtable _unevaluatedSections中,表示尚未evaluated的configkey的集合,可見section例項物件的建立和 handler一樣,都是fetch when need。在後面的操作Getconfig中會使用他。
{
this._unevaluatedSections = new Hashtable();
}
&
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-343236/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 轉:DNS解析過程詳解DNS
- nagios配置過程詳解iOS
- Windows下Jekyll配置過程詳解Windows
- 一個 java 檔案的執行過程詳解Java
- redis 配置檔案詳解Redis
- haproxy配置檔案詳解
- redis配置檔案詳解Redis
- SSH配置檔案詳解
- zookeeper配置檔案詳解
- nginx配置檔案詳解Nginx
- WCF配置檔案詳解
- [轉]:xmake編譯配置過程詳解編譯
- JVM 深入學習:Java 解析 Class 檔案過程解析JVMJava
- Nginx的配置檔案詳解Nginx
- vim的配置檔案詳解
- Hibernate配置檔案詳解
- BIND配置檔案詳解(三)
- Spring 配置檔案詳解Spring
- vsftpd配置檔案詳解FTP
- Nagios配置檔案詳解iOS
- spring配置檔案詳解Spring
- 檔案上傳(解析)漏洞詳解
- .Net Core中的配置檔案原始碼解析原始碼
- vue原始碼解析-圖解diff詳細過程Vue原始碼圖解
- Nginx 配置檔案引數詳解Nginx
- 屬性配置檔案詳解(2)
- Docker Compose 配置檔案詳解Docker
- MyBatis--主配置檔案詳解MyBatis
- influx詳解(二):配置檔案UX
- Struts配置檔案詳細講解
- redis配置檔案引數詳解Redis
- Nginx配置檔案解析Nginx
- redis配置檔案解析Redis
- SpringBoot配置檔案讀取過程分析Spring Boot
- Mysql配置檔案my.ini配置項詳解MySql
- MyBatis 核心配置檔案詳細內容詳解MyBatis
- linux的啟動配置檔案inittab檔案詳解Linux
- PHP配置檔案詳解php.iniPHP