TestableIO/System.IO.Abstractions

Async options for all actions

KristofferStrube opened this issue · 1 comments

Is your feature request related to a problem? Please describe.
Certain systems don't have synchronous options for some File System actions. An example could be when creating directories using the browser File System API. In that API we use the promise-based getDirectoryHandle function to resolve a directory or create it if does not exist. We can call these methods from C# in Blazor where the parallel to a value-returning promise is an async ValueTask. So there is no way to create and return a reference to a directory synchronously as we should do when implementing the Testable.System.IO.Abstractions.IDirectory.CreateDirectory method. I have a wrapper for this API for Blazor (Blazor.FileSystem) that I would like to make a Testable.System.IO.Abstractions compliant version of.

Another problem is with the version of Blazor called Blazor Server where all calls to browser API's have to be asynchronous whether the API uses promises or not since the invocation happens over a socket connection instead of locally. This is the same problem but it exacerbates it further.

I would love it if Testable.System.IO.Abstractions could encompass support for asynchronous-centered file systems as well.

Describe the solution you'd like
A solution to this could be some interfaces parallel to the existing synchronous interfaces. But with asynchronous methods instead of all synchronous ones and asynchronous getter and setter methods for all synchronously accessible properties.

An example could be the following:

public interface IAsyncDirectory : IAsyncFileSystemEntity
{
    ValueTask<IDirectoryInfo> CreateDirectoryAsync(string path);
    Task DeleteAsync(string path);
    Task DeleteAsync(string path, bool recursive);
    ValueTask<IEnumerable<string>> EnumerateDirectoriesAsync(string path);
    ValueTask<IEnumerable<string>> EnumerateDirectoriesAsync(string path, string searchPattern);
    ValueTask<IEnumerable<string>> EnumerateDirectoriesAsync(string path, string searchPattern, SearchOption searchOption);
    // and more ...
}

I'm very open to design ideas, but in the above, I have made IAsyncDirectory inherit from a fictitious IAsyncFileSystemEntity that would define an async accessor method for the FileSystem. From this, I think how the rest of the interfaces would look is pretty clear. If people wanted to support this API as well then it would be very easy to simply call the synchronous versions and return a ValueTask if the specific file system doesn't have an equivalent asynchronous method.

Describe alternatives you've considered
An alternative solution is that you are not interested in supporting the above change as it diverges from the System.IO API surface shape. In that case, I would probably create an OSS project for it that relies on your project for the testable versions, etc.

Additional context
This issue originally started when a person wanted to migrate a WPF application to Blazor using my library. Here I found your library which is super cool since it supplies a common API surface as requested. KristofferStrube/Blazor.FileSystemAccess#39

Thanks for reaching out @KristofferStrube and sorry for the late response!

This library is meant as a pure drop-in replacement for System.IO. Also we want to keep maintenance effort for it as low as possible.

Therefore please go ahead with the a separate project. Or maybe discuss with @gigi81 if it would fit into https://github.com/TestableIO/System.IO.Abstractions.Extensions.

Thanks for your understanding!