Custom configuration processing in. NET 2.0

Source: Internet
Author: User
Tags abstract define constructor empty
   Introduction

In modern software development, various techniques and techniques are becoming more and more dependent on configuration, such as client personalization of user experience, various run-time parameter settings of the system, pluggable plug-in mechanism, and the IOC architecture model based on configuration. Configuration is also from the original binary storage format gradually over to the INI text format so far in the widely used XML format. Configured using XML format, greatly improves the performance of setting data, but there are many inconveniences to manipulating XML configuration in. NET 1.x, especially the storage synchronization mechanism for XML configurations is imperfect, and the framework provides a richer and more manageable mechanism for using. NET 2.0.

The configuration file (Xml) in. NET must be a root node with "<configuration>" and the configuration file is divided into two parts: the configuration declaration area and the data Settings area.

Configuration declaration area: in <configuration> <configSections>, declared by the <section> node.

Data Settings area: Any node that is outside the <configuration> root node except <configSections>.

The data Settings area can be a user-defined hierarchy of any structure, but its "root node" must be defined in advance in the Set declaration area, the runtime will be validated, and a run-time configuration exception will be generated if no declared configuration node is found.

Sample configuration file

<configuration>
<configSections>
<section name= "Datasystems" type= "SWSystem.Data.Configuration.DataSystemsSection, Swsystem.data"/>
</configSections>

<dataSystems>
<datasystem name= "IMRP" currentprovider= "SQLProvider"
<dataprovider name= "Mssqlprovider" type= SWSystem.Data.Providers.SQLDataProvider "datafile=" D:\Zongsoft\Develop 2005\swsystem.data\services\swdataengine.xml "connectionstring=" UID=SA; Pwd=;initial catalog=imrp;data source=127.0.0.1 "/>
<dataprovider name= "Postgresqlprovider" type= SWSystem.Data.Providers.PostgreDataProvider "datafile=" D:\Zongsoft\ Develop 2005\swsystem.data\services\swdataengine.xml "connectionstring=" server=127.0.0.1; port=5432; User Id=postgres; PASSWORD=POSTGRES;DATABASE=IMRP; Encoding=unicode; "/>

<dataModules>
<add name= "Stockmodule" type= "Zongsoft.Applications.iMRP.Business.StockModule, Zongsoft.Applications.iMRP.Business "/>
</dataModules>
</dataSystem>
</dataSystems>
</configuration>


  Overview

To implement a custom configuration in. NET 2.0, you can create a custom configuration section by using a programmatic or declarative (attributed) coding model.

Programming model. This model requires that you create a property for each section attribute to get and/or set its value, and add it to the internal property package of the underlying ConfigurationElement base class.

Declares the model. This relatively simple model, also known as the attribute model, allows you to define a section attribute by using a property, and to decorate it with attributes.

The elements in a configuration file are called basic XML elements or sections. The base element is simply a simple XML tag with related attributes, if any. The simplest form of the section is the same as the basic element. A complex section can include one or more basic elements, a collection of elements, and other sections.

The ConfigurationProperty class represents an attribute or its child element in the configuration node, and all we have to do is configure the properties in the entity class by using the ConfigurationProperty class Maps to the corresponding node attributes (attribute).

   Configuration Statement

To use custom configuration data in a configuration file, you must declare a custom configuration section handler in the declaration area through the <section> node, which has two required properties: Name and type.

Name property: Specifies the names of the configuration sections or elements that are associated with the configuration section handler specified in the Type property. This is the name that the element uses in the configuration file's Settings area.

Type property: Specifies the handler that is used to process the settings section specified by the Name property. Use the following format:
Type= "Configurationsectionhandlerclass, assemblyFileName, Version, Culture, PublicKeyToken"
If the version of the handler is not required, or if it is a zone-free and strongly signed assembly, you can omit the following three items, or you must match the version strictly. Note: The assembly file name does not have its extended file name (usually. dll).

Configuration declarations in the sample configuration file are defined as: <section name= "Datasystems" type= "SWSystem.Data.Configuration.DataSystemsSection, Swsystem.data"/ > indicates that the <dataSystems> node in the data Settings area is handled by the SWSystem.Data.Configuration.DataSystemsSection class and that the class is in the Swsystem.data assembly.

To implement a custom configuration handler class in. NET 1.x, which must implement the IConfigurationSectionHandler interface, it is now only necessary to inherit your handler class from the ConfigurationSection class in. NET 2.0. The processing steps are as follows:

First you define and create an instance of the Configurationpropertycollection class to hold the attributes of the configuration node and all of its child element mappings, but you can also use ConfigurationElement The Properties property in the base class.

The ConfigurationProperty class is then created to map to the corresponding node attribute or child element.

In a type constructor or an instance constructor, add the ConfigurationProperty class instance that you created to the Configurationpropertycollection collection that you have created.

Ultimately, our example configuration handler class might look like this (if you use declarative mode the code does not look so cumbersome, these configuration attribute classes will help you reflect the build when the framework is running, and because of this, it is less efficient to run.) ):

public class Datasystemssection:configurationsection
{
private static readonly ConfigurationProperty _datasystems = new ConfigurationProperty (null, typeof ( Datasystemelementcollection), NULL, configurationpropertyoptions.isdefaultcollection);
private static Configurationpropertycollection _properties = new Configurationpropertycollection ();

Static Datasystemssection ()
{
_properties. ADD (_datasystems);
}

Public Datasystemelementcollection Datasystems
{
Get
{
Return (datasystemelementcollection) Base[_datasystems];
}
}

protected override Configurationpropertycollection Properties
{
Get
{
return _properties;
}
}
}
   node mapping/configuration entity

Create a corresponding configuration entity class for all configuration nodes, in which the attributes (property) correspond to attributes and child elements (collections) in the node. Its writing steps and development methods are similar to handlers, except that our base class becomes configurationelement.

public class Datasystemelement:configurationelement
{
private static readonly ConfigurationProperty _name = new ConfigurationProperty ("name", typeof (String), NULL, NULL, new St Ringvalidator (1), Configurationpropertyoptions.iskey | configurationpropertyoptions.isrequired);
private static readonly ConfigurationProperty _currentprovider = new ConfigurationProperty ("Currentprovider", typeof ( String), String. Empty, configurationpropertyoptions.isrequired);
private static readonly ConfigurationProperty _datamodules = new ConfigurationProperty ("Datamodules", typeof ( Datamoduleelementcollection), NULL, configurationpropertyoptions.none);
private static readonly ConfigurationProperty _dataproviders = new ConfigurationProperty (null, typeof ( Dataproviderelementcollection), NULL, configurationpropertyoptions.isrequired | Configurationpropertyoptions.isdefaultcollection);

private static Configurationpropertycollection _properties = new Configurationpropertycollection ();

#region Type Constructors
Static Datasystemelement ()
{
_properties. ADD (_name);
_properties. ADD (_currentprovider);
_properties. ADD (_dataproviders);
_properties. ADD (_datamodules);
}
#endregion

#region Constructors
Public Datasystemelement ()
{}

Public datasystemelement (string name)
{
This. name = name;
}

Public datasystemelement (string name, String currentprovider)
{
This. name = name;
This. Currentprovidername = Currentprovider;
}
#endregion

#region Public Properties
public string Name
{
Get
{
Return (string) base[_name];
}
Set
{
Base[_name] = value;
}
}

Public String Currentprovidername
{
Get
{
Return (string) This[_currentprovider];
}
Set
{
This[_currentprovider] = value;
}
}

Public Datamoduleelementcollection Datamodules
{
Get
{
Return (datamoduleelementcollection) base[_datamodules];
}
}

Public Dataproviderelementcollection Dataproviders
{
Get
{
Return (dataproviderelementcollection) base[_dataproviders];
}
}
#endregion
}
Note the differences in how <dataProvider> and <dataModules> child elements are handled.

The <dataModules> is a nested collection node under which there are standard <add>, <remove>, <clear> child elements, and the <dataModules> element cannot appear multiple times under the same <dataSystem> node.

The <dataProvider> is a direct set of child nodes under the <dataSystem> node, <dataProvider> is a collection item node that can occur multiple times under the same parent node, so the ConfigurationProperty to which it is mapped The options parameter in the class constructor contains the Configurationpropertyoptions.isdefaultcollection enumeration entry, which indicates. NET Framework constructs a nested section, in addition, you cannot specify the name of its corresponding configuration node, that is, the value of the name parameter in the constructor must be persisted as a null reference ([c#]null/[vb.net]nothing) or an empty string (string.empty/"").

   Node Collection

Creates a class derived from configurationelementcollection that must override (override) an abstract method in a derived class:

Protected abstract ConfigurationElement createnewelement ()
When you load a collection from a configuration file, the method is called to create individual elements. Override this method to create a custom ConfigurationElement object of a specific type.

Protected abstract Object Getelementkey (configurationelement Element)
Gets the key value of the specified configuration element When overridden in a derived class.

For a Non-default node collection class, you must also override the getter for the CollectionType and ElementName read-only properties, which may be the following code:

protected override string ElementName
{
Get
{
return "Dataprovider"; The "Dataprovider" Replace with the Your elementname in collection.
}
}

public override Configurationelementcollectiontype CollectionType
{
Get
{
return configurationelementcollectiontype.basicmap;
}
}
You can override the getter for the Throwonduplicate read-only property to indicate whether adding a duplicate configurationelement to ConfigurationElementCollection will cause an exception to be thrown. By default, an exception is thrown only if the element's CollectionType value is Addremoveclearmap or addremoveclearmapalternate, and if you want a Non-default node collection to not accept duplicates (as is often the case), Then you must override the getter for this property and always return True (true).

Note that elements with the same key and values are not treated as repeating elements, but rather accept such elements without prompting, and that only elements of the same key with different values are treated as repeating elements. The reason is that these elements do not compete. However, you cannot add elements that have the same value and different values because you cannot logically determine which competitive value is valid.

   design pattern of indexers

Typically, you need to define two overloads of indexers (overloads), a read-write indexer that accepts an integer number, and a read-only indexer that accepts a string key value.

Public dataproviderelement This[int Index]
{
Get
{
Return (dataproviderelement) baseget (index);
}
Set
{
if (Baseget (index)!= null)
Baseremoveat (index);

Baseadd (index, value);
}
}

Public new dataproviderelement this[string name]
{
Get
{
Return (dataproviderelement) baseget (name);
}
}
   Other Matters

It is often also necessary to expose some of the methods for collection operations, roughly as follows:

public int IndexOf (dataproviderelement value)
{
return Baseindexof (value);
}

public void Add (dataproviderelement value)
{
Baseadd (value);
}

public void Remove (dataproviderelement value)
{
if (Baseindexof (value) >= 0)
Baseremove (value. Name);
}

public void Remove (string name)
{
Baseremove (name);
}

public void RemoveAt (int index)
{
Baseremoveat (index);
}

public void Clear ()
{
Baseclear ();
}
   Summary

This is just the first article in the basic Technology article in. NET 2.0 that I want to write. In this article, I introduce some basic concepts about configuration, and explain how to customize your own configuration handlers in. NET 2.0, and some of the details you need to be aware of in this process. You've seen that with the expansion of the infrastructure provided in. NET 2.0, we can easily complete the customized configuration customization.

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.