.NET Core的文件系统[2]:FileProvider是个什么东西?
在《读取并监控文件的变化》中,我们通过三个简单的实例演示从编程的角度对文件系统做了初步的体验,接下来我们继续从设计的角度来继续认识它。这个抽象的文件系统以目录的形式来组织文件,我们可以利用它读取某个文件的内容,还可以对目标文件试试监控并捕捉它的变化。这些基本的功能均由相应的FileProvider来提供,从某种意义上讲FileProvider代表了整个文件系统。[ 本文已经同步到《ASP.NET Core框架揭秘》之中]
目录
一、FileProvider
二、FileInfo & GetFileInfo方法
三、DirectoryContents & GetDirectoryContents方法
四、ChangeToken & Watch方法
五、关于路径前缀“/”
六、总结
一、FileProvider
FileProvider是我们对所有实现了IFileProvider接口的所有类型以及对应对象的统称。我们在《读取并监控文件的变化》三个简单的实例演示,它们实际上体现了文件系统承载的三个基本功能,而这个三个基本功能分别体现在IFileProvider接口如下所示的三个方法中。
1: public interface IFileProvider
2: {
3: IFileInfo GetFileInfo(string subpath);
4: IDirectoryContents GetDirectoryContents(string subpath);
5: IChangeToken Watch(string filter);
6: }
二、FileInfo & GetFileInfo方法
虽然文件系统采用目录来组织文件,但是不论是目录还是文件都通过具有如下定义的IFileInfo接口来表示,我们将实现了该接口的类型以及对应对象统称为FileInfo。我们可以通读属性Exists判断指定的目录或者文件是否真实存在,它的另一个属性IsDirectory总是返回False。至于另外两个属性Name和PhysicalPath,它们分别表示文件或者目录的名称和物理路径。属性LastModified返回一个时间戳,表示目录或者文件最终一次被修改的时间。对于一个表示具体文件的FileInfo,我们可以利用属性Length得到文件内容的字节长度。如果我们希望读取文件的内容,可以借助于通过CreateReadStream方法返回的Stream对象来完成。
1: public interface IFileInfo
2: {
3: bool Exists { get; }
4: bool IsDirectory { get; }
5: string Name { get; }
6: string PhysicalPath { get; }
7: DateTimeOffset LastModified { get; }
8: long Length { get; }
9:
10: Stream CreateReadStream();
11: }
IFileProvider的GetFileInfo方法根据指定的路径得到表示所在文件的FileInfo对象,一般来说,这个路径应该是相对应当前FileProvider的相对路径。换句话说,虽然FileInfo可以用于描述目录和文件,但是GetFileInfo方法的目的在于得到指定路径返回的文件而不是目录。当我们调用这个方法的时候,不论我们指定的路径是否存在,该方法总是返回一个具体的FileInfo对象。即使我们指定的路径对应着一个具体的目录,这个FileInfo对象的IsDirectory也总是返回False(它的Exists属性也返回False)。
三、DirectoryContents & GetDirectoryContents方法
如果我们希望得到某个目录的内容,即多少文件或者子目录包含在这个目录下,我们可以调用指定所在目录的路径作为参数调用FileProvider的GetDirectoryContents,目录内容通过该方法返回的DirectoryContents对象来表示。DirectoryContents是对所有实现了具有如下定义的IDirectoryContents接口的所有类型以及对应对象的统称。一个DirectoryContents对象实际上表示一个FileInfo的集合,组成这个集合的所有FileInfo自然就是对所有文件和子目录的描述。和GetFileInfo方法一样,不论指定的目录是否存在,GetDirectoryContents方法总是会返回一个具体的DirectoryContents对象,它的Exists属性会帮助我们确定指定目录是否存在。
1: public interface IDirectoryContents : IEnumerable<IFileInfo>
2: {
3: bool Exists { get; }
4: }
四、ChangeToken & Watch方法
如果我们希望监控FileProvider所在目录或者文件的变化,我们可以调用它的Watch方法,当时前提是对应的FileProvider提供了这样的监控功能。这个方法接受一个字符串类型的参数filter,我们可以利用这个参数指定一个表达式来筛选需要监控的目标目录或文件。就目前预定义的这几个FileProvider来说,只有PhysicalFileProvider提供针对文件的监控功能。对于PhysicalFileProvider来说,它会委托一个FileSystemWatcher对象来完成最终的文件监控任务。在指定删选表达式的时候,我们可以指定需要被监控的某个具体目录或者文件路径,也可以采用下表所示的通配符“*”。
|
Filter |
Description |
|
foobar/data.txt |
存储在目录foobar下的文件data.txt。 |
|
foobar/*.txt |
存储在目录foobar下的所有.txt文件。 |
|
foobar/*.* |
存储在目录foobar下的所有文件。 |
|
foobar//*.* |
存储在目录foobar的所有子目录下的所有文件。 |
Watch方法的返回类型为具有如下定义的IChangeToken接口,我们将实现了该接口的所有类型以及对应对象统称外ChangeToken。ChangeToken可以视为一个与某个数据进行关联,并在数据发生变化对外发送通知的令牌。如果关联的数据发生改变,它的HasChanged属性将变成True。我们可以调用它的RegisterChangeCallback方法注册一个在数据发生改变时可以自动执行的回调。值得一提的是,该方法会以一个IDisposable对象的形式返回注册对象,原则上讲我们应该在适当的时机调用其Dispose方法解除注册的回掉,以免出现内存泄漏的问题。至于IChangeToken接口的另一个属性ActiveChangeCallbacks,它表示当数据发生变化时是否需要主动执行注册的回调操作。
1: public interface IChangeToken
2: {
3: bool HasChanged { get; }
4: bool ActiveChangeCallbacks { get; }
5:
6: IDisposable RegisterChangeCallback(Action<object> callback, object state);
7: }
五、关于路径前缀“/”
一般来说,不论是调用GetFileInfo和GetDirectoryContents方法所指定的目标文件和目录的路径,还是在调用Watch方法指定的筛选表达式,都是一个针对当前FileProvider根目录的相对路径。指定的这个路径可以采用“/”字符作为前缀,但是这个前缀是不必要的。换句话说,如下所示的这两组程序是完全等效的。
1: //路径不包含前缀“/”
2: IFileProvider fileProvider = GetFileProvider();
3: IDirectoryContents dirContents = fileProvider.GetDirectoryContents("foobar");
4: IFileInfo fileInfo = fileProvider.GetFileInfo("foobar/foobar.txt");
5: IChangeToken changeToken = fileProvider.Watch("foobar/*.txt");
6:
7: //路径包含前缀“/”
8: IFileProvider fileProvider = GetFileProvider();
9: IDirectoryContents dirContents = fileProvider.GetDirectoryContents("/foobar");
10: IFileInfo fileInfo = fileProvider.GetFileInfo("/foobar/foobar.txt");
11: IChangeToken changeToken = fileProvider.Watch("/foobar/*.txt");
六、总结
总的来说,以FileProvider为核心的文件系统在设计上看是非常简单的。除了FileProvider,文件系统还涉及到其他一些对象,比如DirectoryContents、FileInfo和ChangeToken。这些对象都具有对应的接口定义,下图所示的UML展示了涉及的这些接口以及它们之间的关系。

.NET Core的文件系统[2]:FileProvider是个什么东西?的更多相关文章
- .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”
FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...
- .NET Core的文件系统[1]:读取并监控文件的变化
ASP.NET Core 具有很多针对文件读取的应用.比如我们倾向于采用JSON文件来定义配置,所以应用就会涉及针对配置文件读取.如果用户发送一个针对物理文件的HTTP请求,应用会根据指定的路径读取目 ...
- FileProvider是个什么东西?
FileProvider是个什么东西? 在<读取并监控文件的变化>中,我们通过三个简单的实例演示从编程的角度对文件系统做了初步的体验,接下来我们继续从设计的角度来继续认识它.这个抽象的文件 ...
- .NET Core的文件系统[3]:由PhysicalFileProvider构建的物理文件系统
ASP.NET Core应用中使用得最多的还是具体的物理文件,比如配置文件.View文件以及网页上的静态文件,物理文件系统的抽象通过PhysicalFileProvider这个FileProvider ...
- .NET Core的文件系统[4]:由EmbeddedFileProvider构建的内嵌(资源)文件系统
一个物理文件可以直接作为资源内嵌到编译生成的程序集中.借助于EmbeddedFileProvider,我们可以统一的编程方式来读取内嵌于某个程序集中的资源文件,不过在这之前我们必须知道如何将一个项目文 ...
- 重新整理 .net core 实践篇—————文件系统[二十二]
前言 简单介绍一下文件系统. 正文 文件系统,主要是下面3个接口组成: IFileProvider IFileInfo IDirectoryContents 那么他们的实现是: physicalFil ...
- 零基础入门学习Python(30)--文件系统:介绍一个高大上的东西
知识点 os,os.path模块中关于文件.目录常用的函数使用方法 在使用os模块,需要先进行import操作: import os os模块中关于文件/目录常用的函数使用方法 函数名 函数作用 示例 ...
- ASP.NET Core 源码学习之 Logging[4]:FileProvider
前面几章介绍了 ASP.NET Core Logging 系统的配置和使用,而对于 Provider ,微软也提供了 Console, Debug, EventSource, TraceSource ...
- ASP.NET Core框架揭秘(持续更新中…)
之前写了一系列关于.NET Core/ASP.NET Core的文章,但是大都是针对RC版本.到了正式的RTM,很多地方都发生了改变,所以我会将之前发布的文章针对正式版本的.NET Core 1.0进 ...
随机推荐
- eclipse 快捷键大全
注:因eclipse版本.电脑配置等原因 有些快捷键可能导致不可用(遇到些许问题可在下方评论) [Ct rl+T] 搜索当前接口的实现类 1. [ALT +/] 此快捷键为用户编辑的好帮手,能为 ...
- Vue + Webpack + Vue-loader 系列教程(2)相关配置篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ 使用预处理器 在 Webpack 中,所有的预处理器需要和一个相应的加载器一同使用.vue- ...
- EntityFramework之DetectChanges's Secrets(三)(我为EF正名)
前言 对于应用程序开发者来说,通常不需要考虑太多对于Entity Framework中的变更追踪(change tracking),但是变更追踪和DetectChanges方法是栈的一部分,在这其中, ...
- 【Web动画】SVG 实现复杂线条动画
在上一篇文章中,我们初步实现了一些利用基本图形就能完成的线条动画: [Web动画]SVG 线条动画入门 当然,事物都是朝着熵增焓减的方向发展的,复杂线条也肯定比有序线条要多. 很多时候,我们无法人工去 ...
- Effective java笔记(二),所有对象的通用方法
Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...
- c#比较两个数组的差异
将DataTable中某一列数据直接转换成数组进行比较,使用的Linq,要引用命名空间using System.Linq; string[] arrRate = dtRate.AsEnumerable ...
- 我理解的MVC
前言 前一阶段对MVC模式及其衍生模式做了一番比较深入的研究和实践,这篇文章也算是一个阶段性的回顾和总结. 经典MVC模式 经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的 ...
- 反应器(Reactor)和主动器(Proactor)
网络方面用的比较多的库是libevent和boost.asio,两者都是跨平台的.其中libevent是基于Reactor实现的,而boost.asio是基于Proactor实现的.Reactor和P ...
- Prometheus 系统监控方案 一
最近一直在折腾时序类型的数据库,经过一段时间项目应用,觉得十分不错.而Prometheus又是刚刚推出不久的开源方案,中文资料较少,所以打算写一系列应用的实践过程分享一下. Prometheus 是什 ...
- Raspkate - 基于.NET的可运行于树莓派的轻量型Web服务器
最近在业余时间玩玩树莓派,刚开始的时候在树莓派里写一些基于wiringPi库的C语言程序来控制树莓派的GPIO引脚,从而控制LED发光二极管的闪烁,后来觉得,是不是可以使用HTML5+jQuery等流 ...