. NET configuration file parsing process

Source: Internet
Author: User
Tags definition config contains goto inheritance key reflection
Process | detailed

In my opinion, the biggest difference between the development of Web project and the development of WinForm is that the web is running on a higher level framework on the framework, that is, ASP. NET Framework, programmer development under the Web can be said to be black box development, not to allow you to define the program entry and execution order, but asp.net to call your various methods, programmers do is a controlled dance. Just as we call NUnit tools to test a DLL, NUnit is a container, a framework, and which method to execute is determined by Nunt. Therefore, there is the page implementation cycle of the state and so on just getting started programmers confused, in fact, the root of the problem is not understand the container and to use the container. For the ASP.net framework of learning, we may as well start from the configuration file.

For program developers, writing profiles is a regular job, if you write a xx.config file, if you do not have detailed comments, others may be difficult to read, there is no good configuration structure, the program also lost vitality. In my opinion, the. NET configuration file is characterized by reflection definition and inheritance.

When we visit the configuration file, we often feel that the configuration file structure is not very suitable for our needs, we need to more easily from the inside the definition of the object, not just key and value, for the custom configuration file has a lot of writing, this is no longer described, interested friends can visit

The Custom configuration section is actually in the application of the. NET configuration file architecture, we first understand the structure of the configuration file, and figure out how the. NET Configuration file works. The following are part of the Machine.config:

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

The definition of <section> in the SDK is:

<section
Name= "section name"
Type= "configuration section handler class, assembly"
Allowdefinition= "everywhere| machineonly| MachineToApplication "
allowlocation= "True|false"/>

The definition of <sectionGroup> is:

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

Let's look at how this structure is leveraged within the. NET Framework. Decompile System.dll Find the GetConfig method, in which we find that the actual work of obtaining config is by default implemented by the Defaultconfiguationsystem class that implements Iconfigurationsystem.

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);
}

let's see Defaultconfigurationsystem again. This class mainly contains the basic information of Machine.config's name path and some URI operations, and the actual getconfig operation is given to the Configuationrecord to handle, this class does not implement any interface, visible he and defaultconfiguration are bound together.
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;}
Internal static string Machineconfigurationfilepath {get;}
One internal static string Mscorlibdirectory {get;}
12
Fields//
Private Configurationrecord _application;
Private Const string configextension = "config";
Private Const string machineconfigfilename = "Machine.config";
Private Const string machineconfigsubdirectory = "Config";
The private const int maxpathsize = 0x400;
19}
20
In fact, all profile analysis and acquisition are implemented in Configuationrecord, as the first step in profile analysis, as we often do-> load a configuration file, which is exposed as load (filename). Defaultconfiguationsystem Init () Method creates a Configuationrecord object with Machine.config and passes it as a parent object to the Configuationrecord object of the current program, provided that the current program has a configuration file, such as Myapp.config, and then loads the current program's Configuration file, which enables inheritance of the configuration file.
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 ());
}
}
}

Now we can focus on the concrete implementation of the Configuationrecord, get a XmlTextWriter in the Load method, and execute the. Scanfactoriesrecursive and Scansectionsrecursive methods.

Reader1 = Configurationrecord.openxmltextreader (filename);
if (reader1!= null)
{
This. Scanfactoriesrecursive (Reader1);
if (reader1. Depth = 1)
{
This. Scansectionsrecursive (reader1, NULL);
}
return true;
}

The Scanfactoriesrecursive method calls one of his overloaded methods to parse the <sectiongroup>,<section>,<remove in the <configsections> >,<clear>, we write the configuration file can not be written in the case of error oh,. NET does not do toslower and so on conversion, directly is "= =". In this method the program will parse the sectiongroup to key=tagkey,value= Configurationrecord.groupsingleton the way to the Ensurefactories, the section is stored in a key=tagkey,value=typestring way, and it is noteworthy that Instead of creating an instance object that implements IConfigurationSectionHandler, the type name (for example: string "System") is not created. Configuration.namevaluesectionhandler ") as a value to ensurefactories, and then the reflection is created when the back getconfig. <remove> is stored as Configurationrecord.removedfactorysingleton. <clear> empty ensurefactories. The tagkey here is a combination of all levels of name, such as "mygroup/mysection" in the form of a delimiter "/". It should be said objectively that this part of the code used a lot of goto statements, the readability is not too good, but it does not have any problems to write.

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;

The Scansectionsrecursive method resolves the section instance in the configuration file and stores its tagkey in the Hashtable _unevaluatedsections. Represents a collection of configkey that are not yet evaluated, and the creation of a section instance object is the same as handler, which is the fetch when need. He will be used in the later Operation GetConfig.

if (this._unevaluatedsections = null)
{
This._unevaluatedsections = new Hashtable ();
}
THIS._UNEVALUATEDSECTIONS[TEXT2] = null;

Now we can see how the GetConfig method executes to get the object we want.

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;
}

If there is a section instance of the corresponding configkey in the _result, it is returned, no then the Configkey is Resolveconfig, the resolved object is saved to the _result and returned to the user. In the Resolveconfig method, you can see that if the current configuration file does not have the required configkey, it will return the parent's section instance, such as the contents of the Machine.config.

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;
}

Then is the evaluate and its subsequent operations, the main is to decompose the Configkey into a string array, a layer to find the corresponding XmlElement, find the corresponding handler to Configkey, if the handler did not create the reflection created, The handler then creates an instance object for the section, which is returned to the user with the following key code:

Configxmldocument Document1 = new Configxmldocument ();
Document1. Loadsingleelement (this._filename, reader);
Config = factory. Create (config, null, Document1. DocumentElement);

Now we're going to Mingbai Dang we use System. What happened when Configurtion.configuationsetting.getconfig.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.