- SetXmlNode ( )
Because the XmlNode class has not constructor(s) and because we need to use it in the next method bellow as a "section" argument in the configuration files, we need to use this public method to ensure that "section" argument is initialized before any use.
/* The document that will be needed to apply the tools provided by DOM technology */<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
XmlDataDocument xmlDocument;
/* This method is used to initialise the XmlNode that will be used to create the section*/
public XmlNode SetXmlNode()
{
//Initialise the xmlDocument
xmlDocument = new XmlDataDocument();
//Create an XmlNode and set it as a xmlDocument element
XmlNode Section = xmlDocument.CreateElement(SectionName);
return Section;
}
Of Corse, this method is a function that returns an XmlNode.
- Create (object parent, object configContext, XmlNode section )
This is the principal method, it helps us create a section witch is an XmlNode in the configuration file profiting that the last one has an Xml format and it can be handled with tools provided by the DOM technology. The method is overloaded by three arguments and returns an object just as it is defined by the IConfigurationSectionHandler interface, but in our case we don't need really an object to be returned, because the final purpose here is only create a section in the configuration file. Therefore, I thought at the first time to set the returned object as null because the function must return something, otherwise, an exception will be thrown. But after a little brain storming, I have had an idea; we can create a Boolean witch called SectionCreated witch plays the role of the turned over object by the Create ( ) method, this last one is set as false at the beginning. Once the section is created and saved, it indicates to the developer and the user that a given section has been created successfully.
public object Create(object oParent, object configContext, XmlNode section)
{
try
{
/* This boolean is used to indicate whether the section is created or not
* if there are not key duplication the corresponding value is true */
bool SectionCreated = false;
/* This variable represent the configuration file*/
configContext = new ExeConfigurationFileMap();
//Setting its path
(configContext as ExeConfigurationFileMap).ExeConfigFilename = Application.StartupPath + "\\" + Application.ProductName + ".exe.config";
// This oParent variable represents the configuration
oParent = ConfigurationManager.OpenMappedExeConfiguration((configContext as ExeConfigurationFileMap), ConfigurationUserLevel.None);
//Load the configuration file into the xmlDocument
xmlDocument.Load((oParent as Configuration).FilePath);
//Select the Root node using the SelectSingleNode DOM method
XmlNode Root = xmlDocument.SelectSingleNode("/configuration");
//Create the node element with the name given by the user
section = xmlDocument.CreateElement(SectionName);
//Add the 'section' node to Root nodes childs
Root.AppendChild(section);
//Create the key attribute for 'section' node
XmlNode Key = xmlDocument.CreateNode(XmlNodeType.Attribute, "key", "");
//Set its value as KeyValue
Key.Value = KeyValue;
//Create the 'serial' attribute for 'section' node
XmlNode serial = xmlDocument.CreateNode(XmlNodeType.Attribute, "serial", "");
//Set its value as SerialValue
serial.Value = SerialValue;
//Add the both attributes to section XmlNode
section.Attributes.SetNamedItem(Key);
section.Attributes.SetNamedItem(serial);
/* This condition is needed to avoid key value duplication*/
if (SectionSaved == true)
{
xmlDocument.Save((oParent as Configuration).FilePath);
SectionCreated = true;
}
/* If all is OK the bolean variable is true, it can indicate to the user that a given section has been added successfuly*/
return SectionCreated;
}
#region Create Exceptions
catch (NotSupportedException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (ConfigurationErrorsException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (XmlException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (InvalidOperationException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (ArgumentException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
#endregion
}
- DuplicationRiskOfKeyValue (string TestKeyValue, string SectionName)
I proposed this void method for one reason is that if a user enters the same value key more than once by carelessness, this can affect negatively the application performance and can cause troubles, therefore, the method mission is to avoid such situation and indicate to the user that the given key value is already been set by throwing a KeyDuplicationException that I derived from the Exception class especially for handling such situation. The method takes two arguments. The first one indicates the tested key value and the second one indicates the name of the targeted section. Of Corse, this method is void and private because the purpose here is that the situation will be handled by the object in the background.
private void DuplicationRiskOfKeyValue(string TestKeyValue, string SectionName)
{
try
{
//This Boolean indicates whether a duplication was happened or not
bool KeyDuplication = false;
//This is the configuration path
string Path = Application.StartupPath + "\\" + Application.ProductName + ".exe.config";
//This is an XmlDataDocument in witch the configuration file is loaded
XmlDataDocument xmlDoc = new XmlDataDocument();
xmlDoc.Load(Path);
//The node list helps us select all created section nodes before
XmlNodeList oNodeList = xmlDoc.SelectNodes("/configuration/" + SectionName);
//This xml node is the key attribute of the section node
XmlNode oKey;
/* This loop help us compare each previous key value section node created before with one that will just been created. If there is values equality then the KeyDuplication Boolean will be set to true and then and exception will be thrown to indicate that a key duplication case has occured*/
foreach (XmlNode node in oNodeList)
{
oKey = xmlDoc.CreateNode(XmlNodeType.Attribute, "key", "");
node.Attributes.GetNamedItem(oKey.Name);
if (node.Attributes.GetNamedItem(oKey.Name).Value == TestKeyValue)
{
KeyDuplication = true;
}
}
// Throw the KeyDuplicationException
if (KeyDuplication == true) throw new KeyDuplicationException();
}
catch (InvalidOperationException caught) { }
catch (ArgumentException caught) { }
}
- GetSectionKeyValue ( string SectionName)
This is a public function that I proposed instead of the GetSection ( ) of the Configuration class, except that the first one doesn't return a section but the key value of the section as a string. I suggested that the function must be static for two reasons. The first one is that the method doesn't depend on the instantiated objects; the second one is that the static methods are better than the dynamic methods in terms of performance.
public static string GetSectionKeyValue(string SectionName)
{
try
{
//The path of the configuration file
string Path = Application.StartupPath + "\\" + Application.ProductName + ".exe.config";
//The xmlDocument in witch the configuration file will be loaded
XmlDataDocument xmlDoc = new XmlDataDocument();
xmlDoc.Load(Path);
//The targeted node
XmlNode oNode = xmlDoc.SelectSingleNode("/configuration/" + SectionName);
//The key attribute
XmlNode oKey = xmlDoc.CreateNode(XmlNodeType.Attribute, "key", "");
oNode.Attributes.GetNamedItem(oKey.Name);
//The key value of the targeted node returned as string
return oNode.Attributes.GetNamedItem(oKey.Name).Value;
}
#region Create Exceptions
catch (NotSupportedException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (ConfigurationErrorsException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (XmlException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (InvalidOperationException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (ArgumentException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
#endregion
}
- GetSectionSerialValue (string SectionName)
This public function helps us get the serial value of a targeted section. It returned the serial value as string object. And I have defined this function as static for the same suggestions as the previous one.
public static string GetSectionSerialValue(string SectionName)
{
try
{
//The path of the configuration file
string Path = Application.StartupPath + "\\" + Application.ProductName + ".exe.config";
//The xmlDocument in witch the configuration file will be loaded
XmlDataDocument xmlDoc = new XmlDataDocument();
xmlDoc.Load(Path);
//The targeted node
XmlNode oNode = xmlDoc.SelectSingleNode("/configuration/" + SectionName);
//The key attribute
XmlNode oKey = xmlDoc.CreateNode(XmlNodeType.Attribute, "Serial", "");
oNode.Attributes.GetNamedItem(oKey.Name);
//The key value of the targeted node returned as string
return oNode.Attributes.GetNamedItem(oKey.Name).Value;
}
#region GetSectionKeyValue Exceptions
catch (NotSupportedException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (System.Xml.XPath.XPathException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (ArgumentException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
catch (NullReferenceException caught)
{
MessageBox.Show(caught.Message, caught.Message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
#endregion
}