作者:性感的aaaaaaaaa_681 | 来源:互联网 | 2023-09-04 10:03
物理的文件有wwwroot下文件(JSCSShtml居多),DLL嵌入的资源(json文件居多),Razor文件,
如何操作这些文件呢,首先先表示这个文件抽象(IFileInfo )
IFileInfo 表示给定文件提供程序中的某个文件。它是文件一个抽象(名称、物理路径,是否存在,IsDirectory:如果 TryGetDirectoryContents 枚举了子目录,则为 True。 ,返回只读流文件string,bytes),
其次,提供文件的操作,IFileProvider,得到目录内容(IFileInfo列表,如果有),得到文件IFileInfo,以及监视
针对以上文件,提供有physicalFileProvider(磁盘)、EmbeddedFileProvider(程序集中)、CompositeFileProvider(IFileProvider 的集合)
针对这些ABP创建了IVirtualFileProvider,它还是基于CompositeFileProvider进行IFileProvider遍历,因此存在优先级。Dymanic>physical?Embedded
下面创建CompositeFileProvider,它由下面组成
dynamicFileProvider:自创建的文件,基于InMemoryFileInfo
PhysicalFileProvider:物理文件,由配置文件AbpVirtualFileSystemOptions导入,如果PhysicalPath存在
InternalVirtualFileProvider:嵌入的文件,基于DictionaryBasedFileProvider,由配置文件AbpVirtualFileSystemOptions导入
protected virtual IFileProvider CreateHybridProvider(IDynamicFileProvider dynamicFileProvider)
{
var fileProviders = new List();
fileProviders.Add(dynamicFileProvider);
if (_options.FileSets.PhysicalPaths.Any())
{
fileProviders.AddRange(
_options.FileSets.PhysicalPaths
.Select(rootPath => new PhysicalFileProvider(rootPath))
.Reverse()
);
}
fileProviders.Add(new InternalVirtualFileProvider(_options));
return new CompositeFileProvider(fileProviders);
}
回到配置文件AbpVirtualFileSystemOptions的FileSets列表,其使用的拓展方法有
AddEmbedded:引入Assembly,注意baseNamespace
list.Add(
new EmbeddedFileSet(
typeof(T).Assembly,
baseNamespace,
baseFolderInProject
)
);
ReplaceEmbeddedByPhysical:
我们需要的是应用程序在开发时直接使用物理文件的能力, 让浏览器刷新时同步Javascript文件的任何更改. ReplaceEmbeddedByPhysical
方法使其成为可能.
分析基于IFileProvider的IVirtualFileProvider实现方法,它的基类型是DictionaryBasedFileProvider,它实现基于IDictionary Files
它在Options的Add方法EmbeddedFileSet,调用AddFiles方法,它去除BaseNamespace,目的是填充了IDictionary字典
foreach (var resourcePath in Assembly.GetManifestResourceNames())
{
if (!BaseNamespace.IsNullOrEmpty() && !resourcePath.StartsWith(BaseNamespace))
{
continue;
}
//上面BaseNamespace不为空或与BaseNamespace开头任一条件都执行以下
//去掉BaseNamespace.开始部分,split(‘.‘)成数组,后两项是文件名,前面是文件夹,join起来成完全的路径
var fullPath = ConvertToRelativePath(resourcePath).EnsureStartsWith(‘/‘);
//如果包括/,说明有目录,则添加目录VirtualDirectoryFileInfo,然后递归,逐层去掉/,直到没有/
if (fullPath.Contains("/"))
{
AddDirectoriesRecursively(files, fullPath.Substring(0, fullPath.LastIndexOf(‘/‘)), lastModificationTime);
}
//添加文件EmbeddedResourceFileInfo
files[fullPath] = new EmbeddedResourceFileInfo(
Assembly,
resourcePath,
fullPath,
CalculateFileName(fullPath),
lastModificationTime
);
}
GetFileInfo方法,输入不能为空的,则根据字典GetOrDefault(路径),它可以得到文件EmbeddedResourceFileInfo,也可以得到VirtualDirectoryFileInfo
GetDirectoryContents,它是基于GetFileInfo得到,输入也不能为空的,如果到是文件名,则直接返回没有找到目录,否则遍历字典的File,它去除输入目录,
找到路径不包含/,注意它可能是文件名,也可能是目录
foreach (var fileInfo in Files.Values)
{
var fullPath = fileInfo.GetVirtualOrPhysicalPathOrNull();
if (!fullPath.StartsWith(directoryPath))
{
continue;
}
var relativePath = fullPath.Substring(directoryPath.Length);
if (relativePath.Contains("/"))
{
continue;
}
fileList.Add(fileInfo);
}
WebContentFileProvider实现
它是PhysicalFileProvider,以及_virtualFileProvider的复合FileProvider
protected virtual IFileProvider CreateFileProvider()
{
return new CompositeFileProvider(
new PhysicalFileProvider(_hostingEnvironment.ContentRootPath),
_virtualFileProvider
);
}
1)GetFileInfo方法,要求以/Pages、/Views、/Themes开始,并且,拓展名以.js,.css,.png。.jpg,.jpeg结束等文件
否则要加上/wwwroot
2) 同理是GetDirectoryContents,以以/Pages、/Views、/Themes开始
1、静态资源,使用MiddleWare
public static IApplicationBuilder UseVirtualFiles(this IApplicationBuilder app)
{
return app.UseStaticFiles(
new StaticFileOptions
{
FileProvider = app.ApplicationServices.GetRequiredService()
}
);
}
2、RazorEngine
//Configure Razor
context.Services.Insert(0,
ServiceDescriptor.Singleton>(
new ConfigureOptions(optiOns=>
{
options.FileProviders.Add(
new RazorViewEngineVirtualFileProvider(
context.Services.GetSingletonInstance>()
)
);
}
)
)
);
模块内添加嵌入式资源
1、AbpLocalizationModule下面有AbpValidation
2、
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiBootstrapModule>("Volo.Abp.AspNetCore.Mvc.UI.Bootstrap");
});
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiMultiTenancyModule>();
});
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiBasicThemeModule>("Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic");
});
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpEmailingModule>();
});
}
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiWidgetsModule>();
});
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpLocalizationModule>("Volo.Abp", "Volo/Abp");
});
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpUiNavigationModule>();
});
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpUiNavigationModule>();
});
Configure(optiOns=>
{
options.FileSets.AddEmbedded<AbpUiModule>();
});