重新整理 .net core 实践篇—————文件系统[二十二]
前言
简单介绍一下文件系统。
正文
文件系统,主要是下面3个接口组成:
- IFileProvider 
- IFileInfo 
- IDirectoryContents 
那么他们的实现是:
- physicalFileProvider 物理文件提供程序 
- enbeddedFileProvider 嵌入式文件提供程序 
- compositeFileProvider 组合文件提供程序 
/// <summary>A read-only file provider abstraction.</summary>
public interface IFileProvider
{
/// <summary>Locate a file at the given path.</summary>
/// <param name="subpath">Relative path that identifies the file.</param>
/// <returns>The file information. Caller must check Exists property.</returns>
IFileInfo GetFileInfo(string subpath);
/// <summary>Enumerate a directory at the given path, if any.</summary>
/// <param name="subpath">Relative path that identifies the directory.</param>
/// <returns>Returns the contents of the directory.</returns>
IDirectoryContents GetDirectoryContents(string subpath);
/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.Primitives.IChangeToken" /> for the specified <paramref name="filter" />.
/// </summary>
/// <param name="filter">Filter string used to determine what files or folders to monitor. Example: **/*.cs, *.*, subFolder/**/*.cshtml.</param>
/// <returns>An <see cref="T:Microsoft.Extensions.Primitives.IChangeToken" /> that is notified when a file matching <paramref name="filter" /> is added, modified or deleted.</returns>
IChangeToken Watch(string filter);
}
IFileProvider A read-only file provider abstraction
只读文件提供程序抽象。
那么这个三个方法分别是:
- GetFileInfo 获取指定文件 
- GetDirectoryContents 获取指定目录,subpath是相对路径 
看下其返回值IDirectoryContents:
  public interface IDirectoryContents : IEnumerable<IFileInfo>, IEnumerable
  {
    /// <summary>True if a directory was located at the given path.</summary>
    bool Exists { get; }
  }
其继承IEnumerable说明其实可以遍历文件的,同时有一个Exists 方法,判断这个目录是否存在
IFileInfo 可以获取的信息如下:
  public interface IFileInfo
  {
    /// <summary>
    /// True if resource exists in the underlying storage system.
    /// </summary>
    bool Exists { get; }
    /// <summary>
    /// The length of the file in bytes, or -1 for a directory or non-existing files.
    /// </summary>
    long Length { get; }
    /// <summary>
    /// The path to the file, including the file name. Return null if the file is not directly accessible.
    /// </summary>
    string PhysicalPath { get; }
    /// <summary>
    /// The name of the file or directory, not including any path.
    /// </summary>
    string Name { get; }
    /// <summary>When the file was last modified</summary>
    DateTimeOffset LastModified { get; }
    /// <summary>
    /// True for the case TryGetDirectoryContents has enumerated a sub-directory
    /// </summary>
    bool IsDirectory { get; }
    /// <summary>
    /// Return file contents as readonly stream. Caller should dispose stream when complete.
    /// </summary>
    /// <returns>The file stream</returns>
    Stream CreateReadStream();
  }
这里面有一个IsDirectory 属性,看来目录也是当成了文件的,这样设计可能是兼容linux的原因吧,一切皆文件。
- 第三个 Watch,看到IChangeToken 就知道肯定是搞监听的。
测试:
static void Main(string[] args)
{
	IFileProvider provider = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory);
	var contents = provider.GetDirectoryContents("/");
	foreach (var item in contents)
	{
		Console.WriteLine(item.Name);
	}
	Console.ReadLine();
}
打印根目录全部文件。

查看内嵌文件:
在根目录创建emb.html,设置为内嵌。
里面为:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    这个是一个内嵌文件
</body>
</html>
测试代码:
IFileProvider provider = new EmbeddedFileProvider(typeof(Program).Assembly);
var html = provider.GetFileInfo("emb.html");
Console.ReadLine();
结果:

下面看下组合文件提供程序:
static void Main(string[] args)
{
	IFileProvider provider1 = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory);
	IFileProvider provider2 = new EmbeddedFileProvider(typeof(Program).Assembly);
	IFileProvider providerSum = new CompositeFileProvider(provider1, provider2);
	var contents = providerSum.GetDirectoryContents("/");
	foreach (var item in contents)
	{
		Console.WriteLine(item.Name);
	}
	Console.ReadLine();
}

简单看下这个组合是如何实现的。
public CompositeFileProvider(params IFileProvider[] fileProviders)
{
  this._fileProviders = fileProviders ?? Array.Empty<IFileProvider>();
}
先是放置在一个数组中,名为_fileProviders 。
看下GetDirectoryContents:
public IDirectoryContents GetDirectoryContents(string subpath)
{
  return (IDirectoryContents) new CompositeDirectoryContents((IList<IFileProvider>) this._fileProviders, subpath);
}
看下CompositeDirectoryContents:
public CompositeDirectoryContents(IList<IFileProvider> fileProviders, string subpath)
{
  if (fileProviders == null)
	throw new ArgumentNullException(nameof (fileProviders));
  this._fileProviders = fileProviders;
  this._subPath = subpath;
}
然后遍历的时候调用:
/// <summary>Creates an enumerator for all files in all providers given.
/// Ensures each item in the collection is distinct.</summary>
/// <returns>An enumerator over all files in all given providers</returns>
public IEnumerator<IFileInfo> GetEnumerator()
{
  this.EnsureFilesAreInitialized();
  return (IEnumerator<IFileInfo>) this._files.GetEnumerator();
}
查看EnsureFilesAreInitialized:
private void EnsureFilesAreInitialized()
{
  this.EnsureDirectoriesAreInitialized();
  if (this._files != null)
	return;
  this._files = new List<IFileInfo>();
  HashSet<string> stringSet = new HashSet<string>();
  for (int index = 0; index < this._directories.Count; ++index)
  {
	foreach (IFileInfo fileInfo in (IEnumerable<IFileInfo>) this._directories[index])
	{
	  if (stringSet.Add(fileInfo.Name))
		this._files.Add(fileInfo);
	}
  }
}
继续查看EnsureDirectoriesAreInitialized:
private void EnsureDirectoriesAreInitialized()
{
  if (this._directories != null)
	return;
  this._directories = new List<IDirectoryContents>();
  foreach (IFileProvider fileProvider in (IEnumerable<IFileProvider>) this._fileProviders)
  {
	IDirectoryContents directoryContents = fileProvider.GetDirectoryContents(this._subPath);
	if (directoryContents != null && directoryContents.Exists)
	{
	  this._exists = true;
	  this._directories.Add(directoryContents);
	}
  }
}
这样看来就是每隔文件的provider 调用GetDirectoryContents,然后再次遍历套娃把文件信息都放入List _files,然后遍历的时候遍历的就是_files。
功能挺少的,这样看来必须是同一个subpath,只能在外面根目录做文章。
结
以上只是个人整理,如有错误,望请指点。
下一节路由与终结点。
重新整理 .net core 实践篇—————文件系统[二十二]的更多相关文章
- 重新整理 .net core 实践篇—————HttpClientFactory[三十二]
		前言 简单整理一下HttpClientFactory . 正文 这个HttpFactory 主要有下面的功能: 管理内部HttpMessageHandler 的生命周期,灵活应对资源问题和DNS刷新问 ... 
- 重新整理 .net core 实践篇————依赖注入应用[二]
		前言 这里介绍一下.net core的依赖注入框架,其中其代码原理在我的另一个整理<<重新整理 1400篇>>中已经写了,故而专门整理应用这一块. 以下只是个人整理,如有问题, ... 
- 重新整理 .net core 实践篇—————工作单元模式[二十六]
		前言 简单整理一下工作单元模式. 正文 工作单元模式有3个特性,也算是其功能: 使用同一上下文 跟踪实体的状态 保障事务一致性 工作单元模式 主要关注事务,所以重点在事务上. 在共享层的基础建设类库中 ... 
- 重新整理 .net core 实践篇————网关[三十六]
		前言 简单整理一下网关. 正文 在介绍网关之前,介绍一下BFF,BFF全称是Backend For Frontend,它负责认证授权,服务聚合,目标是为前端提供服务. 说的通透一点,就是有没有见过这种 ... 
- 重新整理 .net core 实践篇—————路由和终结点[二十三]
		前言 简单整理一下路由和终节点. 正文 路由方式主要有两种: 1.路由模板方式 2.RouteAttribute 方式 路由约束: 1.类型约束 2.范围约束 3.正则表达式 4.是否必选 5.自定义 ... 
- 重新整理 .net core 实践篇——— filter[四十四]
		前言 简单介绍一下filter 正文 filter 的种类,微软文档中写道: 每种筛选器类型都在筛选器管道中的不同阶段执行: 授权筛选器最先运行,用于确定是否已针对请求为用户授权. 如果请求未获授权, ... 
- 重新整理 .net core 实践篇————配置应用[一]
		前言 本来想整理到<<重新整理.net core 计1400篇>>里面去,但是后来一想,整理 .net core 实践篇 是偏于实践,故而分开. 因为是重新整理,那么就从配置开 ... 
- Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十二】
		<Web 前端开发精华文章推荐>2014年第一期(总第二十二期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML ... 
- VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池
		VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池 在上一节我们创建了完整克隆的自动专有桌面池,在创建过程比较缓慢,这次我们将学习创建Vi ... 
随机推荐
- Windows核心编程 第七章 线程的调度、优先级和亲缘性(上)
			第7章 线程的调度.优先级和亲缘性 抢占式操作系统必须使用某种算法来确定哪些线程应该在何时调度和运行多长时间.本章将要介绍Microsoft Windows 98和Windows 2000使用的一些算 ... 
- [CTF]中那些脑洞大开的编码和加密
			[CTF]中那些脑洞大开的编码和加密 摘自:https://www.cnblogs.com/mq0036/p/6544055.html 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会 ... 
- Portswigger web security academy:Stored XSS
			Portswigger web security academy:Stored XSS 目录 Portswigger web security academy:Stored XSS Stored XS ... 
- <JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构
			笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ... 
- mongo中常用的命令
			命令使用mongo shell 执行 1.mongo中增加新字段 mongo shell 进入后执行use table选中要添加字段的库 db.getCollection('表名').update({ ... 
- java-处理大容量文本文件,行内分格符为TAB的方法
			以处理某sql文件为例 源文件中行格式为: 123456 7895433 xxxxx yyyyy zzzzz 行间分隔符为 TAB. 转换完后文件中行的格式为: 123456,7895433,xxx ... 
- Pulsar部署和实践(一)
			前言 本地Docker部署Pulsar消息代理实现消息发布和消息订阅 介绍 相关概念,后面有时间再花时间整理下. 实践步骤 1.使用dokcer本地部署pulsar docker run -it \ ... 
- JavaWeb——JDBC连接池&JDBCTemplate
			今日内容 1. 数据库连接池 2. Spring JDBC : JDBC Template 数据库连接池 1. 概念:其实就是一个容器(集合),存放数据库连接的容器. 当系统初始化好后,容器被创建,容 ... 
- [2021BUAA软工助教]个人第一次阅读作业小结
			BUAA个人阅读作业小结 一.作业要求 https://edu.cnblogs.com/campus/buaa/BUAA_SE_2021_LR/homework/11776 二.评分规则 言之有物,按 ... 
- 3D深色金属哥特3D项目工具小图标icon高清设计素材
			3D深色金属哥特3D项目工具小图标icon高清设计素材 
