IFileProvider
There are decorating adapters to and from IFileProvider instances.
To use IFileProvider decorations, the calling assembly must import the Microsoft.Extensions.FileProviders.Abstractions assembly.
To IFileSystem
The extension method IFileProvider.ToFileSystem() adapts IFileProvider into IFileSystem.
IFileSystem fs = new PhysicalFileProvider(@"C:\Users").ToFileSystem();
Parameters .ToFileSystem(bool canBrowse, bool canObserve, bool canOpen) can be used for limiting the capabilities of the adapted IFileSystem.
IFileProvider fp = new PhysicalFileProvider(@"C:\");
IFileSystem fs = fp.ToFileSystem(
canBrowse: true,
canObserve: true,
canOpen: true);
.AttachDisposable(object) attaches a disposable to be disposed along with the IFileSystem adapter.
IFileProvider fp = new PhysicalFileProvider(@"C:\Users");
IFileSystemDisposable filesystem = fp.ToFileSystem().AttachDisposable(fp);
.AddDisposeAction() attaches a delegate to be ran at dispose. It can be used for disposing the source IFileProvider.
IFileSystemDisposable filesystem = new PhysicalFileProvider(@"C:\Users")
.ToFileSystem()
.AddDisposeAction(fs => fs.FileProviderDisposable?.Dispose());
.BelateDispose() creates a handle that postpones dispose on .Dispose(). Actual dispose will proceed once .Dispose() is called and all belate handles are disposed. This can be used for passing the IFileSystem to a worker thread.
using (var fs = new PhysicalFileProvider(@"C:\Users")
.ToFileSystem()
.AddDisposeAction(f => f.FileProviderDisposable?.Dispose()))
{
fs.Browse("");
// Post pone dispose at end of using()
IDisposable belateDisposeHandle = fs.BelateDispose();
// Start concurrent work
Task.Run(() =>
{
// Do work
Thread.Sleep(100);
fs.GetEntry("");
// Release the belate dispose handle
// FileSystem is actually disposed here
// provided that the using block has exited
// in the main thread.
belateDisposeHandle.Dispose();
});
// using() exists here and starts the dispose fs
}
The adapted IFileSystem can be used as any filesystem that has Open(), Browse() and Observe() features.
IFileSystem fs = new PhysicalFileProvider(@"C:\Users").ToFileSystem();
foreach (var line in fs.VisitTree(depth: 2))
Console.WriteLine(line);
"" ├──"Public" │ ├──"Shared Files" │ ├──"Documents" │ ├──"Downloads" │ ├──"Music" │ ├──"Pictures" │ ├──"Roaming" │ └──"Videos" └──"user" ├──"Contacts" ├──"Desktop" ├──"Documents" ├──"Downloads" ├──"Favorites" ├──"Links" ├──"Music" ├──"OneDrive" ├──"Pictures" └──"Videos"
.Observe() attaches a watcher to the source IFileProvider and adapts incoming events.
IFileSystem fs = new PhysicalFileProvider(@"C:\Users").ToFileSystem();
IObserver<Avalanche.FileSystem.IEvent> observer = new Observer();
using (IDisposable handle = fs.Observe("**", observer))
{
}
Warning
Note that, observing a IFileProvider through IFileSystem adapter browses the subtree of the source IFileProvider and compares snapshots in order to produce change events. If observer uses "**" pattern, it will browse through the whole IFileProvider.
To IFileProvider
IFileSystem.ToFileProvider() adapts IFileProvider into IFileSystem.
IFileProvider fp = FileSystem.OS.ToFileProvider();
.AttachDisposable(object) attaches a disposable to be disposed along with the IFileProvider adapter.
IFileSystem fs = new FileSystem("");
IFileProviderDisposable fp = fs.ToFileProvider().AttachDisposable(fs);
.AddDisposeAction() attaches a delegate to be ran at dispose. It can be used for disposing the source IFileSystem.
IFileProviderDisposable fp = new FileSystem("")
.ToFileProvider()
.AddDisposeAction(fs => fs.FileSystemDisposable?.Dispose());
.BelateDispose() creates a handle that postpones dispose on .Dispose(). Actual dispose will proceed once .Dispose() is called and all belate handles are disposed. This can be used for passing the IFileProvider to a worker thread.
using (var fp = new FileSystem("").ToFileProvider()
.AddDisposeAction(fs => fs.FileSystemDisposable?.Dispose()))
{
fp.GetDirectoryContents("");
// Post pone dispose at end of using()
IDisposable? belateDisposeHandle = fp.BelateDispose();
// Start concurrent work
Task.Run(() =>
{
// Do work
Thread.Sleep(100);
fp.GetDirectoryContents("");
// Release the belate dispose handle
// FileSystem is actually disposed here
// provided that the using block has exited
// in the main thread.
belateDisposeHandle?.Dispose();
});
// using() exists here and starts the dispose fs
}
The adapted IFileProvider can be used as any fileprovider that can GetDirectoryContents(), GetFileInfo(), and Watch().
IFileProvider fp = FileSystem.OS.ToFileProvider();
foreach (var fi in fp.GetDirectoryContents(""))
Console.WriteLine(fi.Name);
C: D: E:
.Watch() attaches a watcher.
IChangeToken token = new FileSystem(@"c:").ToFileProvider().Watch("**");
token.RegisterChangeCallback(o => Console.WriteLine("Changed"), null);