use namespace="System.Collections.Concurrent" functions @{ public class FileWatcher { private readonly HashSet _files = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary> _directories = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); private readonly FileSystemWatcher _watcher; public FileWatcher(string path) { _watcher = new FileSystemWatcher(path); _watcher.IncludeSubdirectories = true; _watcher.EnableRaisingEvents = true; _watcher.Changed += OnWatcherChanged; _watcher.Renamed += OnRenamed; _watcher.Deleted += OnWatcherChanged; _watcher.Created += OnWatcherChanged; } public event Action OnChanged; public void WatchDirectory(string path, string extension) { var extensions = _directories.GetOrAdd(path, _ => new HashSet(StringComparer.OrdinalIgnoreCase)); extensions.Add(extension); } public bool WatchFile(string path) { return _files.Add(path); } public void Dispose() { _watcher.Dispose(); } public bool ReportChange(string newPath, WatcherChangeTypes changeType) { return ReportChange(oldPath: null, newPath: newPath, changeType: changeType); } public bool ReportChange(string oldPath, string newPath, WatcherChangeTypes changeType) { if (HasChanged(oldPath, newPath, changeType)) { if (oldPath != null) { Trace.TraceInformation("{0} -> {1}", oldPath, newPath); } else { Trace.TraceInformation("{0} -> {1}", changeType, newPath); } if (OnChanged != null) { OnChanged(newPath); } return true; } return false; } private void OnRenamed(object sender, RenamedEventArgs e) { ReportChange(e.OldFullPath, e.FullPath, e.ChangeType); } private void OnWatcherChanged(object sender, FileSystemEventArgs e) { ReportChange(e.FullPath, e.ChangeType); } private bool HasChanged(string oldPath, string newPath, WatcherChangeTypes changeType) { // File changes if (_files.Contains(newPath) || (oldPath != null && _files.Contains(oldPath))) { return true; } HashSet extensions; if (_directories.TryGetValue(newPath, out extensions) || _directories.TryGetValue(Path.GetDirectoryName(newPath), out extensions)) { string extension = Path.GetExtension(newPath); if (String.IsNullOrEmpty(extension)) { // Assume it's a directory if (changeType == WatcherChangeTypes.Created || changeType == WatcherChangeTypes.Renamed) { foreach (var e in extensions) { WatchDirectory(newPath, e); } } else if(changeType == WatcherChangeTypes.Deleted) { return true; } // Ignore anything else return false; } return extensions.Contains(extension); } return false; } } }