VC++ Cures for .NET Configuration Change Headaches, Part 2

My previous article presented the various options for reloading changed configuration settings without restarting an application domain where covered. Although none of the solutions was a silver bullet, the article showed the Configuration Application Block from Microsoft's Enterprise Library to be a viable option. However, because the Configuration Application Block is not a simple replacement for the System.Configuration namespace's built-in configuration infrastructure, it imposes a lot of re-work on existing applications.

This article presents a Visual C++ assembly with a custom configuration handler that makes achieving reloadable configuration information much easier.

The .NET Framework has a highly extensible configuration system. You can nominate a custom type that will parse a section of XML in the configuration file and return an Object pointer that represents some form of configuration information. The application code that uses this information can then cast the Object pointer to the appropriate type and use it as required. This form of configuration extension is enabled through custom configuration file handlers, and it has many obvious advantages over rewriting an entire configuration system.

The .NET Framework Library ships with a number of custom configuration handlers, such as NameValueSectionHandler, which returns a NameValueCollection pointer as its configuration data, and DictionarySectionHandler, which returns a Hashtable pointer. Both of these types suffer from the same issue as ConfigurationSettings::AppSettings, in that data changes in the configuration file are not reloaded until an application domain is recycled. However, these built-in types can be leveraged to build a custom configuration handler that will reload configuration data when the underlying configuration file changes.

The most obvious form of extension would be to derive a new type from one of the built-in handlers that provides reload support. NameValueCollection is the most likely candidate for derivation because its usage pattern closely matches that of AppSettings. Unfortunately, the virtual method that needs to be overridden to hook in the reloading behavior is marked with the final method attribute, which means that you cannot derive from it. Rather than use derivation, you can store a NameValueCollection pointer as a member variable and build reloading on top of its XML-parsing functionality.

To implement a custom handler, you need to implement the IConfigurationSectionHandler interface. This interface has a single method—Create—that the configuration infrastructure uses to retrieve the configuration data from the custom handler and pass it to the application code that requires the data. A skeleton handler would look like the following code snippet:

public __gc class
Handler:
public
IConfigurationSectionHandler
{
   public:
   virtual Object* Create(Object* parent, Object* configContext,
                          XmlNode* section)
   {
      return 0;
   }
};

The handler would use the XmlNode pointer that is passed in as a parameter to parse the XML contained in this node and then return an Object pointer that represented the de-serialized form of this data. The reloading handler has no special requirements for the XML or the configuration data holder, and you can build the implementation entirely on top of the NameValueSectionHandler, as shown here:

public __gc class
Handler:
public IConfigurationSectionHandler
{
   private:
   NameValueSectionHandler* _handler;
   NameValueCollection* _configData;

   public:
   virtual Object* Create(Object* parent, Object* configContext,
                          XmlNode* section)
   {
      //load original config data;

      _handler = new NameValueSectionHandler();
      NameValueCollection* configData = 
         dynamic_cast<NameValueCollection*>
      (_handler->Create(parent, configContext, section));
      _configData = new NameValueCollection(configData);


      return _configData;
   }
};

This code simply passes on all the work to a NameValueSectionHandler member variable and returns whatever this object parses from the XML. On top of this functionality, the custom handler needs to monitor changes to the configuration file and get the NameValueSectionHandler member variable to reload its data when it detects a change. The FileSystemWatcher class can monitor the configuration file, and when the data is reloaded, it will need the original values passed in to the Create method and, hence, need to be stored in member variables. The handler now looks like this (new code in italics):

public __gc class
Handler: public IConfigurationSectionHandler
{
   private:
   NameValueSectionHandler* _handler;
   NameValueCollection* _configData;

   Object* _parent;
   Object* _configContext;
   XmlNode* _section;
   String* _configFileName;

   void watcher_Changed(Object* sender, FileSystemEventArgs* e)
   {
   }

   public:
   virtual Object* Create(Object* parent, Object* configContext,
                          XmlNode* section)
   {
      //setup config file watch
      _configFileName = AppDomain::CurrentDomain->
                        SetupInformation->ConfigurationFile;
      FileSystemWatcher* watcher = new
      FileSystemWatcher(Path::GetDirectoryName(_configFileName),
      Path::GetFileName(_configFileName));
      watcher->EnableRaisingEvents = true;
      watcher->Changed +=new FileSystemEventHandler(this,
         &Handler::watcher_Changed);

      //store values for re-read
      _parent = parent;
      _configContext = configContext;
      _section = section;

      //load original config data;

      _handler = new NameValueSectionHandler();
      NameValueCollection* configData = 
         dynamic_cast<NameValueCollection*>
         (_handler->Create(parent, configContext, section));

      _configData = new NameValueCollection(configData);
      return _configData;
   }
};

VC++ Cures for .NET Configuration Change Headaches, Part 2

Insert Article Text Here.


Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-Demand eSeminar DevOps and Cloud are all the rage in IT, but the two terms relating process and computing aren't mutually exclusive. Join us to see how your movement into cloud changes the way you develop, deploy, test and manage, and how DevOps can actually be a good thing when coupled with cloud.

  • On-demand Event Event Date: May 18, 2015 While the idea of using facial and/or gesture recognition to create a modern, intuitive game seems attractive, some developers may want to leverage Unity 3D as a way to accelerate their development efforts. There are many different ways in which Intel and Unity Technologies have been working together to help speed the development of games with the Intel&reag; RealSense™ SDK (software developer kit). Check out this webcast to join a panel of experts as they …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date