using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Threading;
using log4net;
public sealed class ConfigurationWatcher : IConfigurationWatcher
{
private FileInfo _configurationFile;
private IList<string> _configurationSections;
private FileSystemWatcher _fileWatcher;
private Timer _fileSyncDelay;
private FileSystemEventArgs _eventArgs;
private const int FILE_SYNC_DELAY = 5000; //5 seconds
private readonly ILog _logger = LogManager.GetLogger(typeof(ConfigurationWatcher));
internal void InitializeWatcher(FileInfo configurationFile, IList<string> configurationSections)
{
_configurationFile = configurationFile;
if (_configurationFile == null)
{
string file = Assembly.GetEntryAssembly().Location + ".config";
_configurationFile = new FileInfo(file);
_logger.InfoFormat("Setting configuration file to a default of {0}. Exists? {1}", file,_configurationFile.Exists.ToString());
}
_configurationSections = configurationSections;
if (_configurationSections == null || _configurationSections.Count == 0)
{
_configurationSections = new List<string> { "appSettings" };
_logger.DebugFormat(@"Setting area to refresh to a default of ""appSettings."" ");
}
_logger.DebugFormat("Creating new System.IO.FileSystemWatcher to watch the configuration file and subscribing to the Changed event.");
_fileWatcher = new FileSystemWatcher
{
Path = _configurationFile.DirectoryName,
Filter = _configurationFile.Name,
NotifyFilter = (NotifyFilters.CreationTime | NotifyFilters.LastWrite |
NotifyFilters.FileName)
};
_fileWatcher.Changed += OnChange;
_fileWatcher.EnableRaisingEvents = true;
_fileSyncDelay = new Timer(AfterFileSyncDelay, null, -1, -1);
}
public ConfigurationWatcher()
{
InitializeWatcher(null, null);
}
public ConfigurationWatcher(FileInfo configurationFile)
{
InitializeWatcher(configurationFile, null);
}
public ConfigurationWatcher(IList<string> configurationSections)
{
InitializeWatcher(null, configurationSections);
}
public ConfigurationWatcher(FileInfo configurationFile, IList<string> configurationSections)
{
InitializeWatcher(configurationFile, configurationSections);
}
private void AfterFileSyncDelay(object state)
{
InvokeConfigurationChanged(_eventArgs);
}
private void OnChange(object source, FileSystemEventArgs e)
{
foreach (string section in _configurationSections)
{
try
{
ConfigurationManager.RefreshSection(section);
}
catch (Exception ex)
{
_logger.ErrorFormat("There was an error setting {0} section in the configuration file. The error: {1}{2}", section,Environment.NewLine,ex.ToString());
}
}
_eventArgs = e;
_fileSyncDelay.Change(FILE_SYNC_DELAY, -1);
}
public event ConfigurationChangedEventHandler ConfigurationUpdated;
private void InvokeConfigurationChanged(FileSystemEventArgs e)
{
_logger.DebugFormat("Raising ConfigurationUpdated event for {0}", e.Name);
ConfigurationChangedEventHandler configurationChangedHandler = ConfigurationUpdated;
if (configurationChangedHandler != null) configurationChangedHandler(this, e);
}
}