Skip to content
This repository was archived by the owner on Nov 6, 2018. It is now read-only.
This repository was archived by the owner on Nov 6, 2018. It is now read-only.

IFileProvider use case and abstraction issues #206

@dazinator

Description

@dazinator

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions