为 FileSystemWatcher 实施 IDisposable class

Implementing IDisposable for FileSystemWatcher class

我有一个简单的 FeatureToggle class,它使用 FilesSystemWatcher 来监视 app.config 文件。如果 .config 文件发生变化,它将从 appSettings 部分重新加载设置。我让它实现了 IDisposable,但是我不能使用 {} 语句,因为我希望在程序 运行 时监视 .config 文件,但是我确实希望在进程结束时调用 Dispose(),而且我无法将 finally() 块添加到主程序中。我怎样才能调用 Dispose()。我会在这里使用终结器吗?

功能切换:

    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);
                }
            }
        }

文件观察器:

  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;
            }
        }
    }

无论您有 WPF 应用程序、WinForms 应用程序还是服务,所有这些都有事件 Initialized,这是初始化您的 class 和 Closed 的好地方,这是处置它的好地方。 (在控制台应用程序中,您可以简单地尝试所有内容......最后)