Introduction
I always like the philosophy of simplicity. The configuration file serves the purpose of changing program behavior without touching code. The less code touched, the better.
In order to reach that simple goal, it is enough to just use an XmlNode
to present configuration section. Any configuration extension, schema change will not impact that piece of configuration code. Certainly you can take the route of ConfigSection
etc. yet, it defeats the simplicity and code changes are not welcomed easily for people in support roles.
For performance enhancement, in case you access the config value lots of times, you can put a little touch up on the stuff given below.
The Configuration
="1.0" ="utf-8"
<configuration>
<configSections>
<section name="HSONG" type="com.hsong.Configuration.MyConfigHandler, tcustconfig"
allowDefinition="Everywhere"
allowExeDefinition="MachineToApplication"
restartOnExternalChanges="true" />
</configSections>
-->
<HSONG>
<APPSETA>JUNKA</APPSETA>
<APPSETB>
<ANOTHERX>JUNKB</ANOTHERX>
</APPSETB>
</HSONG>
-->
</configuration>
Here is a little explanation: What the above <section>
is telling is that a class about the custom section of HSONG
can be loaded. The class is com.hsong.Configuration.MyConfigHandler
, and the assembly is tcustconfig
.
Well, the next step is to define the very class that handles configurations (com.hsong.Configuration.MyConfigHandler
).
IConfigurationHandler and Code Example
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Xml;
using System.Xml.Serialization;
namespace com.hsong.Configuration
{
public class MyProjConfig
{
private static MyProjConfig theConfig;
private static XmlNode cfgNode = null;
internal static XmlNode ConfigXmlNode
{
set
{
if (cfgNode != null) return;
cfgNode = value;
theConfig = new MyProjConfig();
ConfigurationManager.GetSection("HSONG");
}
}
public static MyProjConfig GetConfig()
{
return theConfig;
}
public int GetCount(string xmlpath)
{
return cfgNode.SelectNodes(xmlpath).Count;
}
public string GetValue(string xmlpath, params int[] index)
{
System.Xml.XmlNodeList ndlist = cfgNode.SelectNodes(xmlpath);
int nnodes = ndlist.Count;
if (nnodes == 0) return null;
int nindex = (index == null || index.Length == 0) ? 0 : index[0];
System.Xml.XmlNode nx = ndlist.Item(nindex);
return nx.InnerXml;
}
}
public class MyConfigHandler : IConfigurationSectionHandler
{
public object Create(object parent, object context, XmlNode node)
{
MyProjConfig.ConfigXmlNode = node;
return MyProjConfig.GetConfig();
}
}
}
namespace tcustconfig
{
class Program
{
static void Main(string[] args)
{
com.hsong.Configuration.MyProjConfig cfg=
(com.hsong.Configuration.MyProjConfig)
System.Configuration.ConfigurationManager.GetSection("HSONG");
string va = cfg.GetValue("APPSETA");
string vb = cfg.GetValue("APPSETB/ANOTHERX");
string vc = cfg.GetValue("APPSETB");
}
}
}
Conclusion
Keep it simple and easy for fellow developers to work with. When your team has lots of code to worry about, you want to have your team focused on business, not trick playing.
History
- 10th April, 2006: Initial post