XML-based configuration file access interface design and implementation (3)
table of Contents
Summary
Add cache support
Increase configuration file monitoring
Add configurationSettings class
Summary
In the two, we implemented the basic functions of XMLConfigReader and XMLConfigWriter. Because XMLConfigReader implemented, each request once, go to parse the configuration file once, the performance is very low. At the same time, we add a configurationSettings class. Used to call XMLConfigReader and XMLConfigWriter to make it the same as those in System.Configuration.
Add cache support
Since the implementation of XMLConfigReader is requested once, parsing the configuration file, and the information of the configuration file will be used in large amounts of the program running, so that the efficiency is too low. Therefore, here is to use to cache.
The cache is actually equivalent to a static variable, which is unique when running throughout the program. With such a variable, the information is stored in this variable, and it can be directly obtained in other places in the program. Thus avoiding Frequent parsing configuration file. Here, we choose to use HashTable as a cache variable.
In MSDN, we can find a nameValueCollection (Key / Value key value) in the System.Configuration namespace. For easy use, we will also store the information after the configuration file is parsed in NameValueCollection. .
After this definition, for the key in the HashTable set to the name of the section (AppSettings / Sockbasesetting, the value value is the object of the NameValueCollection class of all child nodes of this node.
Modify the code. Add a static HashTable variable to XmlConfigReader and modify the relevant function. Get the obtained information directly in this hashtable in the form of NameValueCollection.
Private static hashtable conftypes = new hashtable ();
PRIVATE STRING ROOTNAME;
Public void process () {
XMLTextReader Reader = New XMLTextReader (_FilePath);
While (Reader.Read ()) {
IF (reader.isstartElement ()) {
#Region Analyze the Files
IF (reader.prefix == String.empty)
{
IF (reader.localname == "configuration")
{
Inconfiguration = true;
}
Else if (Inconfiguration == True) {
IF (reader.localname == "add")
{
IF (Reader.GetaTribute ("key") == null || reader.getattribute ("value") == null)
{
Throw New Exception (rootname "key or value is null);
}
AddKey (Tables, Reader.GetaTribute ("Key"), Reader.GetaTribute ("Value"));
}
Else
{
Rootname = reader.localname;
}
}
}
#ndregion
}
Else if (Reader.LocalName == "configuration") {
Inconfiguration = false;}
}
Reader.Close ();
}
Private Void AddKey (String Key, String Value) {
NameValueCollection Collection;
IF (conftypes.containskey) {
Collection = (NameValueCollection) conftypes [rootname];
}
Else {
LOCK (confTypes.syncroot) {
Collection = new namevalueCollection ();
Conftypes.add (rootname, collection);
}
}
Collection.Add (key, value);
}
In the above code, we modified the Process function. Change the original direct return result to call the AddKey function. By a class member rootname temporarily stores the current sectionName, add the obtained Key / Value to the Hashtable by addKey.
Now, after modification, you can't get directly to the value of the key we think to get. So we write a function again.
Public NameValueCollection getCollection (String Sectionname) {
IF (confTypes.containskey) {
Return (NameValueCollection) conftypes [sectionname];
}
Else {
Throw New Exception (Confname "Is Not Found In XmlConfiguration Files");
}
}
Here, we get the NameValueCollection collection of all child nodes of this node through sectionName. In this way, we can get the value we want.
Increase configuration file monitoring
The above code implements the cache of the configuration file. It greatly improves flexibility. But there is a problem, that is, if the configuration file is modified, this cache will not be updated automatically.
To solve this problem, we have to use FileSystemWatcher, to subscribe to file modification messages, and update the cache. Since this configuration file is added to the monitor file table before the first resolution, we modify XMLConfigReader, add one Static FileSystemWatcher, to save the object of the monitoring file, add a static BOOL value indicating whether you have modified. Remove the constructor, make the configuration file to the monitor list at the beginning. The code is as follows:
Private static filesystemWatcher Watch = new filesisness ();
Private static bool ismodify = true;
Public XMLConfigReader (String filepath) {
_filepath = path.getfullpath (filepath) .toupper ();
Watch.includesubdirectories = false;
Watch.path = path.getdirectoryName (FilePath);
Watch.notifyfilter = notifyfilters.size | NotifyFilters.lastwrite
Watch.filter = path.GetFileName (FilePath);
Watch.changed = new filesystemeventhandler (change_even);
Watch.enableraisingevents = true;
}
Since the file modification notification is implemented by the event mechanism, we also need to implement this function, modify the value of IsModify through this function .private void change_even (Object sender, FileSystemEventArgs e) {
Ismodify = true;
}
This is done for the code for the monitoring of the profile, and now it is time to modify our getCollection code.
The modified code is as follows:
Public NameValueCollection getCollection (String Sectionname) {
IF (ismodify) {
LOCK (confTypes.syncroot) {
CONFTYPES.CLEAR ();
PROCESS ();
}
ismodify = false;
}
IF (confTypes.containskey) {
Return (NameValueCollection) conftypes [sectionname];
}
Else {
Throw New Exception (Confname "Is Not Found In XmlConfiguration Files");
}
}
By now, the code of the entire XMLConfigReader has been completed, and the monitoring of the file can be realized to dynamically modify the value in the cache.
Add configurationSettings class
To make it easy to use, we add a CONFIGURATIONSETTINGS class to use his usage and the usage of the class in the System.Configuration namespace. The code is defined as follows:
Public Class ConfigurationSettings: XMLConfigWriter
{
Private static string _filepath = @ "appconfig.xml";
Public Static String DefaultFilePath
Private static xmlconfigreader reader;
{
Get {return _filepath;
Set {_filepath = path.getFullPath (value);
}
Public Static NameValueCollection Appsettings
{
Get {
IF (Reader == NULL) {
Reader = New XmlconfigRead (DefaultFilePath);
}
Return Reader.getCollection ("appsettings");
}
}
Public Static NameValueCollection getConfig (String Sectionname) {
Get {
IF (Reader == NULL) {
Reader = New XmlconfigRead (DefaultFilePath);
}
Return Reader.getCollection (SectionName);
}
}
In this way, it is the same as the system comes with the system.
to sum up