我有一个简单的FeatureToggle类,它使用FilesSystemWatcher来监视app.config文件。如果.config文件发生更改,它将从appSettings部分重新加载设置。我让它实现了IDisposable,但我不能使用{}语句,因为我希望在程序运行时监视.config文件,但是我希望在进程结束时调用Dispose(),我可以' t将finally()块添加到主程序中。如何调用Dispose()。我会在这里使用终结器吗?
FeatureToggle:
public sealed class FeatureToggle : IDisposable
{
private static readonly FeatureToggle instance = new FeatureToggle();
private static FeatureWatcher featureWatcher = new FeatureWatcher();
private static ConcurrentDictionary<string, bool> features = new ConcurrentDictionary<string, bool>();
private bool disposed;
static FeatureToggle()
{
}
private FeatureToggle()
{
}
public static FeatureToggle Instance
{
get
{
return instance;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public bool Enabled(string featureName)
{
string path = this.GetAssemblyPath();
if (featureWatcher.GetWatcher(path) == null)
{
FileSystemWatcher watcher = featureWatcher.AddWatcher(path);
if (watcher != null)
{
watcher.Changed += this.OnChanged;
this.Refresh(path);
}
}
return this.Get(featureName);
}
private void Add(string key, bool value)
{
features.AddOrUpdate(key, value, (k, v) => value);
}
private void Dispose(bool disposing)
{
if (this.disposed)
{
return;
}
if (disposing)
{
featureWatcher.Dispose();
featureWatcher = null;
features = null;
}
}
private bool Get(string key)
{
bool value;
if (features.TryGetValue(key, out value))
{
return value;
}
return false;
}
private string GetAssemblyPath()
{
return AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
}
private IEnumerable<KeyValuePair<string, bool>> LoadConfig(string path)
{
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap { ExeConfigFilename = path };
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(
configMap,
ConfigurationUserLevel.None);
var settings =
config.AppSettings.Settings.Cast<KeyValueConfigurationElement>()
.Where(x => x.Key.StartsWith("FeatureToggle."))
.ToDictionary(o => o.Key.ToString(CultureInfo.InvariantCulture), o => Convert.ToBoolean(o.Value));
return settings;
}
private void OnChanged(object source, FileSystemEventArgs e)
{
// app.config changed - run update
this.Refresh(e.FullPath);
}
private void Refresh(string path)
{
foreach (var kv in this.LoadConfig(path))
{
this.Add(kv.Key, kv.Value);
}
}
}
FileWatcher:
public class FeatureWatcher : IDisposable
{
private static ConcurrentDictionary<string, FileSystemWatcher> watchers;
private bool disposed;
public FeatureWatcher()
{
watchers = new ConcurrentDictionary<string, FileSystemWatcher>();
}
public FileSystemWatcher AddWatcher(string path)
{
if (this.GetWatcher(path) == null)
{
var parentPath = Path.GetDirectoryName(path);
var watcher = new FileSystemWatcher
{
Path = parentPath,
NotifyFilter = NotifyFilters.LastWrite,
Filter = "*.config"
};
watchers.TryAdd(path, watcher);
watcher.EnableRaisingEvents = true;
return watcher;
}
return null;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public FileSystemWatcher GetWatcher(string path)
{
FileSystemWatcher watcher;
if (!watchers.TryGetValue(path, out watcher))
{
return null;
}
return watcher;
}
protected virtual void Dispose(bool disposing)
{
if (this.disposed)
{
return;
}
if (disposing)
{
// Clean up managed resources
if (watchers != null)
{
foreach (var watcher in watchers.Values)
{
watcher.EnableRaisingEvents = false;
watcher.Dispose();
}
watchers = null;
}
this.disposed = true;
}
}
}
答案 0 :(得分:0)
无论您有WPF应用程序,WinForms应用程序还是服务,所有这些都有事件Initialized
,这是初始化您的课程的好地方,Closed
,这是一个好地方处置它。 (在控制台应用程序中,您可以简单地将所有内容放入try..finally)