基于ASP.NET Core的模块化设计: 虚拟文件系统
Abp中文网(https://cn.abp.io/)提供翻译字幕
基于ASP.NET Core的模块化设计: 虚拟文件系统
简介
创建模块化的应用程序很困难. 构建模块化的用户界面更加困难. 需要单独开发模块的页面和组件,但是最后要把它们集成在一起像单个UI一样
创建这样的模块化架构之前需要构建一个强大的基础设施,这就是我们在开源的ABP[1]项目中尝试做的事情
在本文中我会重点介绍虚拟文件系统,它是模块化基础设施的组要组成部分,并解释我们为什么需要它,以及如何在ASP.NET CORE的基础之上开发虚拟文件系统
本文的视频演示请看这里[2]
用户界面组件
典型的ASP.NET CORE MVC Web应用程序UI由静态和动态资源组成

静态资源包括Java,css,image...等文件. 这些资源请求由Static Files中间件响应处理. 它们通常位于程序的wwwroot下
动态资源是Razor视图,页面和组件. 它们由Razor引擎处理,编译和呈现
静态和动态文件通常都位于物理文件系统中(虽然最新的ASP.NET CORE有预编译选项,但要点是相同的)
模块化应用程序中的用户界面组件
在模块化应用程序中, UI组件分散到各个模块中, 通常嵌入到模块程序集中(DLL文件)中

静态文件中间件和Razor视图引擎无法处理分布在模块程序集之间的资源
虚拟文件系统
虚拟文件系统是一个适配器(包装器),使ASP.NET Core可以使用物理文件系统以外的资源

我们的虚拟文件系统实现可以使用三种类型的文件位置
•嵌入式文件: 位于DLL中的文件作为嵌入式资源. 这些资源在应用程序启动时注册到虚拟文件系统•物理文件: 位于web应用程序下的文件(静态资源的wwwroot文件夹,视图的根文件夹,页面..等). 它是向后兼容的•动态文件: 运行时生成的文件(例如动态js/css bundle文件)
动态文件可以覆盖物理文件, 物理文件可以覆盖嵌入文件(如果位于同一路径中). 通过这种方式应用程序可以覆盖模块的UI组件(如CSS文件,JS文件或视图)以便进行自定义
虚拟文件注册
模块应该在应用程序启动时向虚拟文件系统注册/添加自己的嵌入式资源.我们已经为此创建了VirtualFileSystemOptions. 用法示例:
context.Services.Configure<VirtualFileSystemOptions>(options => { options .FileSets .AddEmbedded<MyModule>(); });
上方的代码将MyModule类的程序集中的所有嵌入资源添加到虚拟文件系统(VFS)中,当所有的模块都在VFS中注册后,我们就会在内存中的字典/集合中提供一个文件列表及其路径(嵌入式命名空间转换为路径)
IFileProvider接口
ASP.NET Core使用IFileProvider接口从文件系统中读取文件:
public interface IFileProvider { IFileInfo GetFileInfo(string subpath); IDirectoryContents GetDirectoryContents(string subpath); IChangeToken Watch(string filter); }
•GetFileInfo方法从给定的路径读取文件信息和内容. 如果给定文件不存在,则返回NotFoundFileInfo•GetDirectoryContents方法用于获取目录中的文件和目录列表. 如果给定的目录不存在会返回NotFoundDirectoryContents(可以返回单例实例:NotFoundDirectoryContents.Singleton)•Watch方法用于在给定路径中文件或文件夹发生更改时收到通知. 过滤器可以包含通配符(如'*')
很显然我们应该实现这个接口从嵌入式/动态文件中返回文件,不过我不会在本文中分享实现部分,如果你想了解详细信息,请参阅我们的实现[3]和文档[4]
配置Razor视图引擎
当我们实现了虚拟文件系统,我们就可以配置RazorViewEngineOptions来添加新的自定义文件提供程序:
context.Services.Configure<RazorViewEngineOptions>(options => { options.FileProviders.Insert(0, new MyVirtualFileProvider()); });
替换静态文件中间件
通常我们使用app.UseStaticFiles向浏览器提供物理文件,不过要使用虚拟文件系统,我们需要替换它. 这部分也很简单. 我们可以编写这个一个扩展方法:
public static void UseVirtualFiles(this IApplicationBuilder app) { app.UseStaticFiles( new StaticFileOptions { FileProvider = new MyVirtualFileProvider() } ); }
MyVirtualFileProvider是我们示例的IFileProvider实现. 你可以将FileProvider设置为任何IFileProvider接口的实现类
最后我们使用UseVirtualFiles方法替换UseVirtualFiles:
app.UseVirtualFiles();
写在最后
我试图简单的描述为什么开发模块化的ASP.NET Core Mvc应用程序会需要虚拟文件系统以及如何实现它
我计划根据我的ABP框架[5]开发经验,在ASP.NET Core上发布更多模块化应用程序开发的文章
References
[1] ABP: https://cn.abp.io
[2] 这里: https://www.bilibili.com/video/av47031992?from=search&seid=6709357480596566187
[3] 实现: https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.VirtualFileSystem
[4] 文档: https://cn.abp.io/documents/abp/latest/Virtual-File-System
[5] ABP框架: https://cn.abp.io/
浙公网安备 33010602011771号