AddThis Social Bookmark Button

Print

Beginnings of a Flexible .NET Architecture: A Simplified Config Service
Pages: 1, 2, 3

Implementation

The approach is simple enough. All of our configuration will sit in one section. There will be classes like DefaultConfig, which will absorb this long XML section. Once absorbed, the DefaultConfig will walk through every node of the XML and make entries in a dictionary (or hashtable) for each key and value. This dictionary will then satisfy client requests for keys.



Section handler code


    public class SimpleConfigurationSectionHandler :IConfigurationSectionHandler
    {
      public object Create(object parent, object configContext, XmlNode section)
      {
        return section;
      } // end of method
    } // end of class

DefaultConfig Code


public class DefaultConfig : IConfig {

// keep a dictionary of values
private IDictionary m_keyValuePairs

// implement methods of IConfig using the above 
// dictionary details left to you

//  Constructor, where it reads your SimpleConfiguration 
// XML node using the section handler above
    public DefaultConfig()
    {
      // read the xml section for general config
      // Section name: SimpleConfiguration
      XmlNode xmlNode =
        (XmlNode)System
          .Configuration
          .ConfigurationSettings
          .GetConfig("SimpleConfiguration");

      if(xmlNode != null)
      {
      m_keyValuePairs = createDictionary(m_genConfigXmlNode);
      }
    }
}

// Here is the createdictionary
    private IDictionary createDictionary(XmlNode genConfigXmlNode)
    {
      IDictionary ht = new Hashtable();
      if(genConfigXmlNode != null && 
        genConfigXmlNode.ChildNodes != null &&
        genConfigXmlNode.ChildNodes.Count > 0)
    {
      // walk through each node
      // if it is a leaf node add it to the hash table
      // if it is not  continue the process

      walkTheNode(ht,"",genConfigXmlNode);
      }
      return ht;
    }

//  Here is how you walk the nodes recursively 
// to get your keys
private void walkTheNode(IDictionary ht, string parent, XmlNode node)
{
    if(node != null)
   {
     if (node.NodeType == XmlNodeType.Comment)
    {
      return;
    }
    if (node.HasChildNodes == false)
    {
      if (node.NodeType == XmlNodeType.Text)
      {
        // no children
        string leaf = node.Value;
        ht.Add(parent.ToLower(),leaf);
        // end of the recursive call
       return;
      }
     else if (node.NodeType == XmlNodeType.CDATA)
     {
        XmlCDataSection cdataSection = (
        System.Xml.XmlCDataSection)node;
        string leaf = cdataSection.Data;
        ht.Add(parent.ToLower(),leaf);
        // end of the recursive call
        return;
     }
     else
        {
        string key = parent + "/" + node.Name;
        string val = "";
        ht.Add(key.ToLower(), val);
        return;
        }
     }
     else
    {
      string newparent = parent + "/" + node.Name;
      // has children
      // walk all the children
     for(int i=0;i<node.ChildNodes.Count;i++)
     {
        // recursive call
       walkTheNode(ht,newparent,node.ChildNodes[i]);
     }
    }
  }
}

One caveat while coding this: pay special attention to how CDATA and empty text nodes are treated!

Related Reading

Programming .NET Web Services
By Alex Ferrara, Matthew MacDonald

Conclusion

I hope to have conveyed that one can simplify the process of accessing configuration variables from config files, be they one or many.

This article has:

  • Showed examples of how such a configuration service could be used.
  • Showed how to embed HTML segments into the XML file and how to retrieve them accurately.
  • Showed partial implementation code to implement such a service.

In the next article in this series, we will take this simple-minded configuration service and extend it into a FactoryService that allows much more flexibility in your architectures.

References

  • "Evolving interfaces and implementations for backward compatibility" (Vol. 6, Issue 6, Java Developers Journal), by Satya Komatineni. Find out how one can write frameworks that can withstand changes over time.
  • Design Patterns (Addison Wesley). Series of design patterns, of which factory is one.

Satya Komatineni is the CTO at Indent, Inc. and the author of Aspire, an open source web development RAD tool for J2EE/XML.


Return to .NET DevCenter