/// <summary> /// Adds a File watcher under the specified integration name and directory. /// Allows a callback to be registered for when any file Create/Delete/Rename/Modify occurs. /// </summary> /// <param name="integrationName">Name of the registration. Used later to remove the file watcher.</param> /// <param name="directory">Directory to watch.</param> /// <param name="actionCallback">Callback for when any Create/Delete/Rename/Modify event occurs (All data about the event is lost). Wont occur more than once every second</param> public void AddFileWatcher(string integrationName, string directory, IntegrationFilesModifiedDelegate actionCallback) { // Create 2 entries. // First one is to map an integration name to a directory. This makes it so we can deregister by integration name // Second one is to store the actual file watcher data that we need to dispose of later. this.FileWatcherCache.Set(integrationName, directory); this.FileWatcherCache.GetOrCreate(directory, (entry) => this.CreateFileWatcherForIntegration(entry, integrationName, directory, actionCallback)); }
private FileWatcherData CreateFileWatcherForIntegration(ICacheEntry cacheEntry, string integrationName, string directory, IntegrationFilesModifiedDelegate callback) { var fileWatcher = new FileSystemWatcher(directory) { NotifyFilter = NotifyFilters.Attributes | NotifyFilters.FileName | NotifyFilters.LastWrite, IncludeSubdirectories = false, EnableRaisingEvents = true }; // Add observables for each of the event types. // Each of them just returns a boolean because we need a shared return type from the observable. // We only care that *something* changed, we don't care what actually changed. var changedFileObserable = Observable.FromEventPattern <FileSystemEventHandler, FileSystemEventArgs>(h => fileWatcher.Changed += h, h => fileWatcher.Changed -= h) .Select(x => true); var createdFileObserable = Observable.FromEventPattern <FileSystemEventHandler, FileSystemEventArgs>(h => fileWatcher.Created += h, h => fileWatcher.Created -= h) .Select(x => true); var deletedFileObserable = Observable.FromEventPattern <FileSystemEventHandler, FileSystemEventArgs>(h => fileWatcher.Deleted += h, h => fileWatcher.Deleted -= h) .Select(x => true); var renamedFileObserable = Observable.FromEventPattern <RenamedEventHandler, RenamedEventArgs>(h => fileWatcher.Renamed += h, h => fileWatcher.Renamed -= h) .Select(x => true); // Merge all the different file watcher events into 1 observable // This allows us to throttle all the events coming through so we don't get more than 1 per second. var fileWatcherSubscription = Observable.Merge(changedFileObserable, createdFileObserable, deletedFileObserable, renamedFileObserable) .Throttle(TimeSpan.FromSeconds(1)) .Subscribe(_ => callback?.Invoke(directory, integrationName)); cacheEntry.RegisterPostEvictionCallback(this.OnCacheEntryEvicted); this.ApplicationLifetime.ApplicationStopping.Register(() => this.RemoveFileWatcher(integrationName)); return(new FileWatcherData(fileWatcher, fileWatcherSubscription)); }