Created
January 3, 2024 01:18
-
-
Save dwcullop/8282abaf55282be7ca11b38d1878c7f9 to your computer and use it in GitHub Desktop.
Represent the file system as an Observable ChangeSet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Reactive.Disposables; | |
using System.Reactive.Linq; | |
using DynamicData; | |
namespace DareWare.Utils; | |
public static class FileSystemObservable | |
{ | |
public static IObservable<IChangeSet<FileSystemInfo, string>> Create(string path, string filter, bool includeSubDirectories, bool includeError = true) => | |
Observable.Create<IChangeSet<FileSystemInfo, string>>(observer => | |
{ | |
var fsw = new FileSystemWatcher(path, filter) | |
{ | |
IncludeSubdirectories = includeSubDirectories, | |
EnableRaisingEvents = true | |
}; | |
var sub = fsw.AsObservableChangeSet().SubscribeSafe(observer); | |
var errorSub = includeError | |
? fsw.ObserveError().Subscribe(args => observer.OnError(args.GetException())) | |
: Disposable.Empty; | |
return new CompositeDisposable(sub, errorSub, fsw); | |
}); | |
public static IObservable<IChangeSet<FileSystemInfo, string>> AsObservableChangeSet(this FileSystemWatcher fsw) => | |
ObservableChangeSet.Create<FileSystemInfo, string>(cache => | |
{ | |
cache.Edit(updater => | |
updater.AddOrUpdate( | |
Directory.EnumerateFileSystemEntries(fsw.Path, fsw.Filter, fsw.IncludeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) | |
.Select(p => GetInfo(p)))); | |
return Observable.Merge( | |
fsw.ObserveChanged().Select(OnChanged), | |
fsw.ObserveCreated().Select(OnCreated), | |
fsw.ObserveDeleted().Select(OnDeleted), | |
fsw.ObserveRenamed().Select(OnRenamed)) | |
.Subscribe(cache.Edit); | |
}, | |
fsi => fsi.FullName); | |
private static FileSystemInfo GetInfo(string fullPath) => | |
Directory.Exists(fullPath) ? new DirectoryInfo(fullPath) : new FileInfo(fullPath); | |
private static Action<ISourceUpdater<FileSystemInfo, string>> OnChanged(FileSystemEventArgs args) => | |
updater => updater.AddOrUpdate(GetInfo(args.FullPath)); | |
private static Action<ISourceUpdater<FileSystemInfo, string>> OnCreated(FileSystemEventArgs args) => | |
updater => updater.AddOrUpdate(GetInfo(args.FullPath)); | |
private static Action<ISourceUpdater<FileSystemInfo, string>> OnDeleted(FileSystemEventArgs args) => | |
updater => updater.RemoveKey(args.FullPath); | |
private static Action<ISourceUpdater<FileSystemInfo, string>> OnRenamed(RenamedEventArgs args) => | |
updater => | |
{ | |
updater.RemoveKey(args.OldFullPath); | |
updater.AddOrUpdate(GetInfo(args.FullPath)); | |
}; | |
private static IObservable<FileSystemEventArgs> ObserveChanged(this FileSystemWatcher watcher) => | |
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>( | |
o => watcher.Changed += o, | |
o => watcher.Changed -= o) | |
.Select(args => args.EventArgs); | |
private static IObservable<FileSystemEventArgs> ObserveCreated(this FileSystemWatcher watcher) => | |
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>( | |
o => watcher.Created += o, | |
o => watcher.Created -= o) | |
.Select(args => args.EventArgs); | |
private static IObservable<FileSystemEventArgs> ObserveDeleted(this FileSystemWatcher watcher) => | |
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>( | |
o => watcher.Deleted += o, | |
o => watcher.Deleted -= o) | |
.Select(args => args.EventArgs); | |
private static IObservable<RenamedEventArgs> ObserveRenamed(this FileSystemWatcher watcher) => | |
Observable.FromEventPattern<RenamedEventHandler, RenamedEventArgs>( | |
o => watcher.Renamed += o, | |
o => watcher.Renamed -= o) | |
.Select(args => args.EventArgs); | |
private static IObservable<ErrorEventArgs> ObserveError(this FileSystemWatcher watcher) => | |
Observable.FromEventPattern<ErrorEventHandler, ErrorEventArgs>( | |
o => watcher.Error += o, | |
o => watcher.Error -= o) | |
.Select(args => args.EventArgs); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment