InMemoryFileProvider
dazinator opened this issue · 17 comments
An "in memory" implementation of an IFileProvider
might be useful to allow providing access to content defined in memory (obviously) which is useful especially during unit tests.
You can ofcourse mock the IFileProvider
interface, but this gets quite complex when you have to also support change token notifications.
It would be nice if there was an InMemory implementation with an API for adding / removing content (at specific subpaths), and for "updating" existing content - which would trigger change notifications, for the purpose of Watch().
Interesting idea, though I think this could be a sample or a contrib project rather than a supported thing.
The nice thing about this would be that it would be a reasonable solution that we could point users to for limitations in our current file provider implementations. For instance, @dazinator's solution listed here - #184 (comment) - could be rewritten as an in memory file provider.
@pranavkm - I ended up creating an in memory file provider in the end.. its probably not optimal but it works for me! Here are its tests: https://github.com/dazinator/NetPack/blob/rjs/src/NetPack.Tests/FileProvider/InMemoryFileProviderTests.cs
If you refactor it in to a separate GitHub project and publish packages it to NuGet.org, we could direct people to it in the project's README. Is that something you might be interested in?
Sure I'd be happy to do that - it might be a little while though before I can get some time to do it.
I have started this, with a view to contributing a RequestPathFileProvider
and an InMemoryFileProvider
here: https://github.com/dazinator/Dazinator.AspNet.Extensions.FileProviders/blob/master/README.md
Once its ready i'll distribute on NuGet.
I am just comparing the test coverage for my InMemoryFileProvider
to the tests you have for the Physical File Provider, to make sure my provider is aligned. I noticed you have this test for the PhysicalFileProvider on Windows.. and I am having trouble understanding the behaviour its asserting or why its desirable.
The test looks like this
[ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux, SkipReason = "Testing Windows specific behaviour on leading slashes.")]
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Testing Windows specific behaviour on leading slashes.")]
[InlineData("/")]
[InlineData("///")]
[InlineData("/\\/")]
[InlineData("\\/\\/")]
public void GetFileInfoReturnsPhysicalFileInfoForValidPathsWithLeadingSlashes_Windows(string path)
{
GetFileInfoReturnsPhysicalFileInfoForValidPathsWithLeadingSlashes(path);
}
public void GetFileInfoReturnsPhysicalFileInfoForValidPathsWithLeadingSlashes(string path)
{
using (var provider = new PhysicalFileProvider(Path.GetTempPath()))
{
var info = provider.GetFileInfo(path);
Assert.IsType(typeof(PhysicalFileInfo), info);
}
}
I am wondering why, when requesting a File named /
or ///
(or any of the other slash combinations it's testing) should it be returning a PhysicalFileInfo
- considering that none of those paths are valid for a file name. I could understand if it was resolving them to a directory perhaps?
@JunTaoLuo any idea on what this test is attempting to do? It looks like it's attempting to basically create a FileInfo(Path.Combine(dir, "/'))
Yes, these are not really valid filenames. They should really be a combination of slashes followed by a filename, for example /\\/file.txt
. These tests were added to test the handling of leading slashes for file providers in a way that's consistent with the filesystem. On Windows files like {fileproviderroot}\///\file.txt
can be resolved to the actual file {fileproviderroot}\file.txt
. However, for the tests, the slashes by themselves were sufficient to make sure GetFileInfo
will return a PhysicalFileInfo
even if it's empty. For reference, the original issue was aspnet/StaticFiles#147.
Thanks for clarifying! Seems like if the file does not exist, irrespective of how slashes are handled for its path, the correct behaviour would be to return a NotFoundFileInfo! Not that it matters a huge deal as people obviously shouldn't be upcasting IFileInfo's anyway :-)
Hi Guys and Gals - In terms of globbing (pattern matching) - is there anything I can leverage built in to .NET yet? I don't want to touch file system, I just want to do a basic:
var glob = new Glob("/some/pattern/*txt");
var isMatched = glob.IsMatch("/some/pattern/foo.txt");
I have been playing with https://github.com/kthompson/csharp-glob but it has some issues.
@pranavkm thanks for that. It doesn't look like the full glob spec is implemented by the matcher just yet, do you know if there are plans to do that in the future? The owner of https://github.com/kthompson/csharp-glob is considering porting to asp.net core and publishing on NuGet which might fill this gap in the meantime.
We haven't gotten any requests for missing features with the globbing library as yet, but we'd certainly be open to enhancing it if you have specific work items in mind.
Ok. I can see #236 already tracks extending the globbing. I'll leave that as a seperate issue!
I have finished implementing the InMemoryFileProvider
and RequestPathFileProvider
and this is being distributed via NuGet
So will close this now!
I also have an idea to implement another FileProvider that will let you add mapping for any existing file or directory path, something like:
var someFileProvider = hosting.WebRootFileProvider;
var virtualFileProvider = new VirtualFileProvider(someFileProvider);
virtualFileProvider.Map("/wwwroot/foo.txt").As("/myspecialfile.txt");
virtualFileProvider.Map("/wwwroot/foo.txt").As("/myotherfile.txt");
``
The idea being `/wwwroot/foo.txt` would then be resolvable on /myspecialfile.txt or /myotherfile.txt.
Anyway, that will come later! Thanks for the guidance and help.
`
Feel free to send an update to the README to add a link to the InMemoryFileProvider package.
PR submitted.