国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
.NET配置文件解析過程詳解

在我看來,WEB project的開發(fā)與WINFORM的開發(fā)最大的區(qū)別在于web的運行是在Framework上更高一層框架上運行,即ASPNET框架,程序員在web下的開發(fā)可以說是黑盒開發(fā),不是讓你去定義程序入口和執(zhí)行順序,而是asp.net來調(diào)用你的各個方法,程序員做的一切都是一種受控的舞蹈。就像我們調(diào)用nunit之類的工具來測試一個dll一樣,nunit是容器,是框架,執(zhí)行哪個方法是由nunt來決定的。因此,也就有了頁面執(zhí)行周期各狀態(tài)等令剛?cè)腴T的程序員困惑不已的事,其實,究其根源,在于不了解容器而去使用容器。對于asp.net框架的學(xué)習,我們不妨從配置文件開始。

對于程序開發(fā)者而言,寫配置文件是經(jīng)常性的工作,如果你寫了一個xx.config文件,如果沒有詳盡的注釋,別人恐怕很難讀懂,沒有良好的配置架構(gòu),程序也失去了活力。在我看來,.net配置文件的特點在于反射定義和繼承性。

我們訪問配置文件時經(jīng)常覺得配置文件的結(jié)構(gòu)不太符合我們的需要,我們需要從里面更方便地獲得自己定義的對象,而不僅僅是keyvalue,對于自定義配置文件的著述已有很多,在此不再描述,有興趣的朋友可以訪問

 

自定義配置節(jié)其實還是在.net配置文件架構(gòu)的應(yīng)用而已,我們先來搞懂配置文件的結(jié)構(gòu),弄清楚.net配置文件的運行方式。下面是machine.config的一部分內(nèi)容:

 

 

 

 

 

 

<configSections>
     
<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<section>的定義為:

<section
   
name="section name"
   type
="configuration section handler class, assembly"
   allowDefinition
="Everywhere|MachineOnly|MachineToApplication" 
   allowLocation
="true|false" />

<sectionGroup>的定義為:

<sectionGroup
   
name="section group name"/>
</sectionGroup>

 

 

 

 

 

 

 

 

  我們來看看.net框架內(nèi)是如何利用這種結(jié)構(gòu)的。反編譯System.dll找到GetConfig方法,在里面我們發(fā)現(xiàn)實際獲取config的工作默認是由實現(xiàn)了IConfigurationSystemDefaultConfiguationSystem類來實現(xiàn)的。

public static object GetConfig(string sectionName)
{
      
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);
}

 

 

 

  我們再來看DefaultConfigurationSystem,這個類主要包含了machine.config的名稱路徑的基本信息和一些uri操作,而實際的GetConfig的操作交給了ConfiguationRecord來處理,這個類沒有實現(xiàn)任何接口,可見他和DefaultConfiguration是綁定在一起的。
 1internal class DefaultConfigurationSystem : IConfigurationSystem
 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里實現(xiàn)的,作為配置文件分析的第一步,正如我們經(jīng)常做的一樣->加載一個配置文件,這個方法公開為 Load(filename)。DefaultConfiguationSystem的Init()方法中用machine.config創(chuàng)建了一個ConfiguationRecord對象,并將其作為父對象傳遞給當前程序的ConfiguationRecord對象,當然前提是當前程序有配置文件,比如myapp.config,然后再加載當前程序的配置文件,從而實現(xiàn)配置文件的繼承。
void IConfigurationSystem.Init()
{
      
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());
            }

      }

}

 

現(xiàn)在我們可以專注于configuationrecord的具體實現(xiàn)了,load方法中得到一個xmltextwriter,并執(zhí)行.scanfactoriesrecursive和scansectionsrecursive方法。

 reader1 = ConfigurationRecord.OpenXmlTextReader(filename);
            
if (reader1 != null)
            
{
                  
this.ScanFactoriesRecursive(reader1);
                  
if (reader1.Depth == 1)
                  
{
                        
this.ScanSectionsRecursive(reader1, null);
                  }

                  
return true;
            }

 scanfactoriesrecursive方法會調(diào)用他的一個重載方法來解析<configsections>中的<sectiongroup>,<section>,<remove>,<clear>,我們寫配置文件時大小寫可不能寫錯哦,.net沒有做toslower之類的轉(zhuǎn)換,直接就是 “== “。在這個方法里程序會將解析得到的sectiongroup以key=tagkey,value= ConfigurationRecord.GroupSingleton的方式存到EnsureFactories里,將section以key=tagkey,value=typestring的方式儲存,值得注意的是,這里并沒有創(chuàng)建實現(xiàn)IConfigurationSectionHandler的實例對象,而是將其類型名(比如:字符串”system.Configuration.NameValueSectionHandler”)作為值到EnsureFactories,等到后面GetConfig的時候再來反射創(chuàng)建。<remove>則存為ConfigurationRecord.RemovedFactorySingleton。<clear>就清空EnsureFactories。這里的tagkey是各級name的組合,比如”mygroup/mysection”這樣以分隔符”/”組合的形式。應(yīng)該客觀地說這部分代碼用了很多goto語句,可讀性不是太好,但這樣寫也確實沒有什么問題。

   this.CheckRequiredAttribute(text3, "name", reader);
            
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實例對象的創(chuàng)建和handler一樣,都是fetch when need。在后面的操作Getconfig中會使用他。

    if (this._unevaluatedSections == null)
            
{
                  
this._unevaluatedSections = new Hashtable();
            }

            
this._unevaluatedSections[text2] = null;

現(xiàn)在我們就可以看getconfig方法是怎么來執(zhí)行得到我們想要的對象的。

public object GetConfig(string configKey)
{
      
if (this._error != null)
      
{
            
throw this._error;
      }

      
if (this._results.Contains(configKey))
      
{
            
return this._results[configKey];
      }

      
object obj1 = this.ResolveConfig(configKey);
      
lock (this._results.SyncRoot)
      
{
            
this._results[configKey] = obj1;
      }

      
return obj1;
}

如果_result中有對應(yīng)configkey的section實例,就返回,沒有則需要對configkey進行resolveconfig,將解析到的對象保存到_result中并返回給用戶。在resolveconfig方法中,可以看到如果當前的配置文件中沒有要求的configkey就會返回父級的section實例,比如machine.config里的內(nèi)容。

public object ResolveConfig(string configKey)
{
      Hashtable hashtable1 
= this._unevaluatedSections;
      
if ((hashtable1 != null&& hashtable1.Contains(configKey))
      
{
            
return this.Evaluate(configKey);
      }

      
if (this._parent != null)
      
{
            
return this._parent.GetConfig(configKey);
      }

      
return null;
}

 

然后就是evaluate及其后續(xù)操作了,主要就是將configkey分解成字符串數(shù)組,一層層地去找對應(yīng)的xmlelement,找到后傳給configkey對應(yīng)的handler,如果該handler沒有創(chuàng)建則反射創(chuàng)建,然后由該handler創(chuàng)建section的實例對象,返回給用戶,該部分關(guān)鍵代碼如下:

  ConfigXmlDocument document1 = new ConfigXmlDocument();
  document1.LoadSingleElement(
this._filename, reader);
 config 
= factory.Create(config, null, document1.DocumentElement);

 現(xiàn)在我們就明白了當我們用system..configurtion.configuationsetting.getconfig的時候發(fā)生過什么了。

作者:  來源:  (責任編輯:webjx) 
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
在C#中如何讀取配置文件 - CookBlack - 博客園
C# 讀寫Config文件(App.config)
用XML文件保存配置信息的一個類(C#)
C#操作配置文件中appSetting,connectionStrings節(jié)點
Struts的資源文件時如何初始化的--struts源碼學(xué)習 - 輪上飛 - BlogJa...
INI配置文件解析C函數(shù)庫
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服