Home All Groups Group Topic Archive Search About

Sample code to make your code reload data that changed in config file

Author
13 Jun 2006 5:55 PM
delphiconsultingguy
The concept is simple, create a custom section handler for your data,
and make it responsible for retrieving new data.  It will know there's
new data because of the FileSystemWatcher instance.  For example, for
the app.config file below:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="myConfig"
type="MyConfig.MyConfigSectionHandler,liveConfigReader" />
    </configSections>
    <myConfig>
        <level>5</level>
    </myConfig>
</configuration>


(remember during testing to make changes to the *.exe.config file that
is created in the /bin directory, not the app.config)

You can make the 'level' a live parameter with the following section
handler code:

using System.Configuration;
using System.Xml;
using System;
using System.IO;
using System.Collections.Specialized;

namespace MyConfig
{
  public class MyConfigSectionHandler : IConfigurationSectionHandler
  {
    public virtual object Create(object parent,object
configContext,XmlNode section)
    {
      return new MyConfigSection(section);
    }
  }

  public class MyConfigSection
  {
    public static bool mIsDataValid = false;
    private string mRootName = null;
    FileSystemWatcher myWatcher;
    NameValueCollection mData;

    public MyConfigSection(XmlNode section)
    {
      LoadXML(section);
      SetUpFileWatcher();
    }

    public int Level
    {
      get
      {
        if (mIsDataValid == false)
        {
          LoadConfig();
        }
        return Convert.ToInt32(mData["level"]);
      }
    }

    private void SetUpFileWatcher()
    {
      FileInfo configFile = new
FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
      string configPath = configFile.DirectoryName;
      string configName = configFile.Name;

      try
      {
        myWatcher = new FileSystemWatcher(configPath);
        myWatcher.Filter = configName;
        myWatcher.NotifyFilter = NotifyFilters.LastWrite;
        myWatcher.Changed += new
FileSystemEventHandler(myWatcher_Changed);
        myWatcher.EnableRaisingEvents = true;
      }
      catch(Exception ex)
      {
        throw new ConfigurationException("Unable to initialize
FileSystemWatcher for configuration file", ex);
      }
    }

    private void LoadXML(XmlNode section)
    {
      mData = new NameValueCollection();

      XmlNode root = section;
      mRootName = root.Name;
      foreach (XmlElement element in root.ChildNodes)
      {
        mData.Add(element.Name, element.InnerText);
      }
      mIsDataValid = true;
    }

    public void LoadConfig()
    {
      XmlDocument doc = new XmlDocument();
      try
      {

doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
      }
      catch (Exception ex)
      {
        string temp = ex.Message;
      }
      XmlNodeList nodes = doc.GetElementsByTagName(mRootName);
      if (nodes.Count > 0)
      {
        LoadXML(nodes[0]);
      }
      else
      {
        throw new ConfigurationException("Configuration section " +
mRootName + " not found");
      }
    }

    private void myWatcher_Changed(object sender, FileSystemEventArgs
e)
    {
      mIsDataValid = false;
    }
  }
}



to test this, create a project called liveConfigReader (as indicated in
the section type in the config file) with a single button with a click
event that does the following:

    private void button1_Click(object sender, System.EventArgs e)
    {
      MyConfigSection s =
(MyConfigSection)ConfigurationSettings.GetConfig("myConfig");
      MessageBox.Show("Level: " + s.Level.ToString());
    }


probably can be optimized quite a bit, but it should get you started

right back at ya,
Sean

AddThis Social Bookmark Button