虛擬文件系統使得管理物理上不存在於文件系統中(磁盤)的文件成爲可能. 它主要用於將(js, css, image, cshtml ...)文件嵌入到程序集中, 並在運行時將它們象物理文件一樣使用。
Volo.Abp.VirtualFileSystem nuget包
Volo.Abp.VirtualFileSystem是虛擬文件系統的核心包. 使用程序包管理器控制檯(PMC)將其安裝到項目中:
Install-Package Volo.Abp.VirtualFileSystem
啓動模板默認已經安裝了此nuget包, 所以在大多數情況下你不需要手動安裝它.
然後你可以在module中添加 AbpVirtualFileSystemModule 依賴項:
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpVirtualFileSystemModule))]
public class MyModule : AbpModule
{
//...
}
}
註冊嵌入式文件
要將文件嵌入到程序集中, 首先需要把該文件標記爲嵌入式資源. 最簡單的方式是在 解決方案管理器 中選擇文件, 然後找到 "屬性" 窗口將 "生成操作" 設置爲 "嵌入式資源". 例如:
如果需要添加多個文件, 這樣做會很乏味. 作爲選擇, 你可以直接編輯 .csproj 文件:
<ItemGroup>
<EmbeddedResource Include="MyResources\**\*.*" />
<Content Remove="MyResources\**\*.*" />
</ItemGroup>
此配置以遞歸方式添加項目的 MyResources 文件夾下的所有文件(包括將來新添加的文件).
然後需要使用 AbpVirtualFileSystemOptions
來配置模塊, 以便將嵌入式文件註冊到虛擬文件系統. 例如:
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpVirtualFileSystemModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
//Register all embedded files of this assembly to the virtual file system
options.FileSets.AddEmbedded<MyModule>("YourRootNameSpace");
});
//...
}
}
}
AddEmbedded
擴展方法需要一個類, 從給定類的程序集中查找所有嵌入文件, 並將它們註冊到虛擬文件系統. 它還有更簡潔的寫法:
options.FileSets.Add(new EmbeddedFileSet(typeof(MyModule).Assembly), "YourRootNameSpace");
"YourRootNameSpace" 是項目的根命名空間名字. 如果你的項目的根命名空間名字爲空,則無需傳遞此參數.
獲取虛擬文件: IVirtualFileProvider
將文件嵌入到程序集中並註冊到虛擬文件系統後, 可以使用IVirtualFileProvider
來獲取文件或目錄內容:
public class MyService
{
private readonly IVirtualFileProvider _virtualFileProvider;
public MyService(IVirtualFileProvider virtualFileProvider)
{
_virtualFileProvider = virtualFileProvider;
}
public void Foo()
{
//Getting a single file
var file = _virtualFileProvider.GetFileInfo("/MyResources/js/test.js");
var fileContent = file.ReadAsString(); //ReadAsString is an extension method of ABP
//Getting all files/directories under a directory
var directoryContents = _virtualFileProvider.GetDirectoryContents("/MyResources/js");
}
}
在開發過程中處理嵌入式文件
將文件嵌入到模塊程序集中並能夠通過引用程序集(或添加nuget包)在另一個項目中使用它對於創建可重用模塊非常有價值. 但是, 這使得開發模塊本身變得有點困難.
假設你正在開發一個包含嵌入式JavaScript文件的模塊. 當你更改文件時, 你必須重新編譯項目, 重新啓動應用程序並刷新瀏覽器頁面以使更改生效. 顯然, 這是非常耗時和乏味的.
我們需要的是應用程序在開發時直接使用物理文件的能力, 讓瀏覽器刷新時同步JavaScript文件的任何更改. ReplaceEmbeddedByPhysical
方法使其成爲可能.
下面的示例展示了應用程序依賴於包含嵌入文件的模塊("MyModule"), 並且應用程序可以在開發過程中直接使用模塊的源代碼.
[DependsOn(typeof(MyModule))]
public class MyWebAppModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment()) //only for development time
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
//ReplaceEmbeddedByPhysical gets the root folder of the MyModule project
options.FileSets.ReplaceEmbeddedByPhysical<MyModule>(
Path.Combine(hostingEnvironment.ContentRootPath, "..\\MyModuleProject")
);
});
}
//...
}
}
上面的代碼假設MyWebAppModule
和MyModule
是Visual Studio解決方案中的兩個不同的項目, MyWebAppModule
依賴於MyModule
。
ASP.NET Core 集成
虛擬文件系統與 ASP.NET Core 無縫集成:
- 虛擬文件可以像Web應用程序上的物理(靜態)文件一樣使用.
- Razor Views, Razor Pages, js, css, 圖像文件和所有其他Web內容可以嵌入到程序集中並像物理文件一樣使用.
- 應用程序(或其他模塊)可以覆蓋模塊的虛擬文件, 就像將具有相同名稱和擴展名的文件放入虛擬文件的同一文件夾中一樣.
虛擬文件中間件
虛擬文件中間件用於向客戶端/瀏覽器提供嵌入式(js, css, image ...)文件, 就像 wwwroot 文件夾中的物理(靜態)文件一樣. 在靜態文件中間件之後添加它, 如下所示:
app.UseVirtualFiles();
在靜態文件中間件之後添加虛擬文件中間件, 使得通過在虛擬文件相同的位置放置物理文件, 從而用物理文件覆蓋虛擬文件成爲可能.
虛擬文件中間件可以虛擬wwwroot文件夾中的內容 - 就像靜態文件一樣.
Views & Pages
無需任何配置即可在應用程序中使用嵌入式的 razor Views/pages. 只需要將它們放置在要開發的模塊中的標準 Views/Pages 虛擬文件夾即可.
如果模塊/應用程序將新文件放置同一位置, 則會覆蓋嵌入式的 Views/Pages.