为FileSystemWatcher类实现IDisposable

时间:2015-03-23 15:26:40

标签: c# .net c#-4.0

我有一个简单的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;
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

无论您有WPF应用程序,WinForms应用程序还是服务,所有这些都有事件Initialized,这是初始化您的课程的好地方,Closed,这是一个好地方处置它。 (在控制台应用程序中,您可以简单地将所有内容放入try..finally)