Decoration
The IFileSystems.Decorate(IOption) extension method decorates a filesystem with new decorated options. Decoration options is an intersection of filesystem's options and the options in the parameters, so decoration reduces features.
IFileSystem ram = new MemoryFileSystem();
IFileSystem rom = ram.Decorate(Option.ReadOnly);
IFileSystems.AsReadOnly() is same as IFileSystems.Decorate(Option.ReadOnly).
IFileSystem rom = ram.AsReadOnly();
Option.NoBrowse prevents browsing, hiding files.
IFileSystem invisible = ram.Decorate(Option.NoBrowse);
Option.SubPath(subpath) option exposes only a subtree of the decorated filesystem. The subpath argument must end with slash "/", or else it mounts filename prefix, e.g. "tmp-".
IFileSystem ram = new MemoryFileSystem();
ram.CreateDirectory("tmp/dir/");
ram.CreateFile("tmp/dir/file.txt", new byte[] { 32, 32, 32, 32, 32, 32, 32, 32, 32 });
IFileSystem tmp = ram.Decorate(Option.SubPath("tmp/"));
tmp.PrintTreeTo(Console.Out, format: FileSystemPrintTreeExtensions.Format.DefaultPath);
└── dir/ └── dir/file.txt
.AddSourceToBeDisposed() adds source objects to be disposed along with the decoration.
MemoryFileSystem ram = new MemoryFileSystem();
IFileSystemDisposable rom = ram.Decorate(Option.ReadOnly).AddSourceToBeDisposed();
// Do work ...
rom.Dispose();
Decorations implement IDisposeAttachable and IDisposeBelatable which allows to attach disposable objects.
MemoryFileSystem ram = new MemoryFileSystem();
ram.CreateDirectory("tmp/dir/");
ram.CreateFile("tmp/dir/file.txt", new byte[] { 32, 32, 32, 32, 32, 32, 32, 32, 32 });
IFileSystemDisposable rom = ram.Decorate(Option.ReadOnly).AttachDisposable(ram);
// Do work ...
rom.Dispose();
If multiple decorations are used, the source reference can be 'forgotten' after construction if belate dispose handles are passed over to decorations.
// Create ram filesystem
MemoryFileSystem ram = new MemoryFileSystem();
ram.CreateDirectory("tmp/dir/");
ram.CreateFile("tmp/dir/file.txt", new byte[] { 32, 32, 32, 32, 32, 32, 32, 32, 32 });
// Create decorations
IFileSystemDisposable rom = ram.Decorate(Option.ReadOnly).AttachDisposable(ram.BelateDispose());
IFileSystemDisposable tmp = ram.Decorate(Option.SubPath("tmp/")).AttachDisposable(ram.BelateDispose());
ram.Dispose(); // <- is actually postponed
// Do work ...
// Dispose rom1 and tmp, disposes ram as well
rom.Dispose();
tmp.Dispose();
Concat
FileSystems.Concat(IFileSystem[]) method composes IFileSystem instances into one.
IFileSystem ram = new MemoryFileSystem();
IFileSystem os = FileSystem.OS;
IFileSystem fp = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory).ToFileSystem()
.AddDisposeAction(fs => fs.FileProviderDisposable?.Dispose());
IFileSystem embedded = new EmbeddedFileSystem(Assembly.GetExecutingAssembly());
IFileSystem composition = FileSystemExtensions.Concat(ram, os, fp, embedded)
.AttachDisposable(embedded)
.AttachDisposable(fp)
.AttachDisposable(os);
Composed set of files can be browsed.
foreach (var entry in composition.VisitTree(depth: 1))
Console.WriteLine(entry);
Files can be read from the composed set.
using Stream s = composition.OpenStream("docs.example-file.txt", FileMode.Open, FileAccess.Read, FileShare.Read);
Console.WriteLine(s.Length);
If two files have same name and path, the file in the first IFileSystem overshadows files from later IFileSystems.
IFileSystem ram1 = new MemoryFileSystem();
IFileSystem ram2 = new MemoryFileSystem();
IFileSystem composition = FileSystemExtensions.Concat(ram1, ram2);
// Create file of 1024 bytes
ram1.CreateFile("file.txt", new byte[1024]);
// Create file of 10 bytes
ram2.CreateFile("file.txt", new byte[10]);
// Get only one entry size of 1024 bytes.
composition.PrintTreeTo(Console.Out, format: FileSystemPrintTreeExtensions.Format.Default | FileSystemPrintTreeExtensions.Format.Length);
"" └── "file.txt" 1024
FileSystems.Concat((IFileSystem, IOption)[]) applies options to the filesystems.
IFileSystem filesystem = FileSystem.Application;
IFileSystem overrides = new MemoryFileSystem();
IFileSystem composition = FileSystemExtensions.Concat(
(filesystem, null),
(overrides, Option.ReadOnly)
);