IFileProvider use case and abstraction issues
See original GitHub issueFrom @dazinator on Monday, June 27, 2016 5:13:04 AM
Questioning whether the IFileProvider
abstraction needs improving (or its implementations) - due to following issues. I am finding usage of the abstraction needs to be different for different providers, so in essence you have to cater for all specific implementations and the IFileProvider abstraction isn’t helpful.
Example use case…
I want an RC2 application to list all available CSS files that are themes for the application, so the user can select one and apply a theme to the site.
In order to distinguish a theme file from other files, the rule I am using is, it must live in a Css/Themes directory. However, in addition to supporting just physical files (from the web applications wwwroot/css/themes directory), the application should also support the ability for theme files to live within referenced projects within the solution.
Here is an example solution directory structure:
WebApplication/wwwroot/css/themes/theme1.css WebApplication/wwwroot/css/themes/theme2.css ModuleA/wwwroot/css/themes/moduleA.css ModuleB/wwwroot/css/themes/moduleB.css
In order to support files located in referenced projects, it means actually embedding the files into the assembly and using an EmbeddedFileProvider over those assemblies. CopyToOutput is useless because its non transitive
So to fulfil the use case, the application starts and creates an “EmbeddedFileProvider” for the referenced project assemblies, pointing to their “wwwroot” folders, as well as a PhysicalFileProvider for the main web applications “wwwroot” directory, and then wraps those in a CompositeFileProvider to give one IFileProvider instance that we can work with to query for Theme files…
Now given the IFileProvider
instance, which is CompositeFileProvider
we want to list the themes css files. If things were aligned it would be as simple as:
var allThemesFiles = fileProvider.GetDirectoryContents("css/themes")
And that would give you all files within that directory. However because EmbeddedFileProvider
doesn’t support / preserve directory information, GetDirectoryContents
doesn’t actually work - so we only get the PhysicalFiles when doing this. Well GetDirectoryContents
does work for EmbeddedFileProvider
but only for the root because it’s just a single directory, i.e fileProvider.GetDirectoryContents("")
returns all files embedded in the assembly. So the application now has to worry about what Providers are in the CompositeProvider, and cater for specific ones like the EmbeddedFileProvider
. For instance, for EmbeddedFileProvider
it needs to loop through all files in the root (single directory) and try to determine if the originated from a css/themes directory based on the name - where “/” was replaced with “.”, i.e:
// all embedded files actually just live in the root directory.
var allFiles = fileProvider.GetDirectoryContents("");
foreach (var file in allFiles)
{
if (file.Name.StartsWith("css.themes"))
{
// theme?
}
}
Ofcourse, doing a fileProvider.GetDirectoryContents("");
on an IFileProvider (which is a composite in my example) could yield hundreds of files depending upon your application, and we don;t want to check all of those files with this logic which it is particular to Embedded
files only.
So in reality, this means we actually need to check the IFileProvider instance, cast it to a composite, check the providers it is wrapping, loop through them, upcast the Embedded ones, and then add our fileProvider.GetDirectoryContents("");
check to find the themes files differently for Embedded providers only.
This is just all yucky imho, is there not a better way? Finding someway to preserve directory information on compile (similar to preserveCompilationContext for dependencies information perhaps) and then restore from that at runtime, such that EmbeddedFileProvider
could support directories would solve this imho.
For example, could we perhaps, at build / compile time, generate and embed a txt file, containing the preserved directory information for embedded files, (a manifest of sorts), and then use this special file at runtime to restore directory information to allow EmbeddedFileProvider
to support directories again.
Copied from original issue: aspnet/FileSystem#206
Issue Analytics
- State:
- Created 6 years ago
- Comments:20 (1 by maintainers)
Top GitHub Comments
@Eilon this can be closed as there was a new manifest embedded file provider introduced to address this.
Good catch, thank you!