. NET Core File System [2]: What is FileProvider ?, Corefileprovider
In "reading and monitoring file changes", we use three simple examples to demonstrate the preliminary experience of the file system from the programming perspective, next we will continue to understand it from the design perspective. This abstract file system organizes files in the form of directories. We can use it to read the content of a file, and try to monitor the target file and capture its changes. These basic functions are provided by the corresponding FileProvider. In a sense, FileProvider represents the entire file system. [This Article has been synchronized to ASP. NET Core framework secrets]
Directory
1. FileProvider
Ii. FileInfo & GetFileInfo Method
3. DirectoryContents & GetDirectoryContents Method
Iv. ChangeToken & Watch Method
V. Path prefix "/"
Vi. Summary
1. FileProvider
FileProvider is a general term for all types and corresponding objects that implement the IFileProvider interface. The three simple examples in "reading and monitoring file changes" show that they actually reflect the three basic functions carried by the file system, these three basic functions are reflected in the three methods shown in the following figure of the IFileProvider interface.
1: public interface IFileProvider
2: {
3: IFileInfo GetFileInfo(string subpath);
4: IDirectoryContents GetDirectoryContents(string subpath);
5: IChangeToken Watch(string filter);
6: }
Ii. FileInfo & GetFileInfo Method
Although the file system uses directories to organize files, both directories and files are represented by the IFileInfo interface defined below. We implement the interface type and corresponding objects collectively referred to as FileInfo. We can read the Exists attribute to determine whether the specified directory or file Exists. The IsDirectory attribute of the specified directory always returns False. For the other two attributes Name and PhysicalPath, they indicate the Name and physical path of the file or directory respectively. LastModified returns a timestamp, indicating the last time the directory or file was modified. For a FileInfo that represents a specific object, we can use the attribute Length to get the object content's byte Length. If you want to read the file content, you can use the Stream object returned by the CreateReadStream method.
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: }
The GetFileInfo method of IFileProvider obtains the FileInfo object of the file according to the specified path. In general, this path should be the relative path of the current FileProvider. In other words, although FileInfo can be used to describe directories and files, the GetFileInfo method aims to get the files returned from a specified path instead of directories. When we call this method, no matter whether the specified path exists or not, this method always returns a specific FileInfo object. Even if the specified path corresponds to a specific directory, the IsDirectory of this FileInfo object always returns False (its Exists attribute also returns False ).
3. DirectoryContents & GetDirectoryContents Method
If we want to get the content of a directory, that is, how many files or subdirectories are contained in this directory, we can call the path of the specified directory as the parameter to call GetDirectoryContents of FileProvider, the directory content is expressed by the DirectoryContents object returned by this method. DirectoryContents is a general term for all types and corresponding objects of the IDirectoryContents interface with the following definitions. A DirectoryContents object actually represents a set of FileInfo. All FileInfo that makes up this set is naturally a description of all files and subdirectories. Like the GetFileInfo method, the GetDirectoryContents method always returns a specific DirectoryContents object regardless of whether the specified directory Exists. Its Exists attribute will help us determine whether the specified directory Exists.
1: public interface IDirectoryContents : IEnumerable<IFileInfo>
2: {
3: bool Exists { get; }
4: }
Iv. ChangeToken & Watch Method
If we want to monitor the changes in the directory or file where FileProvider is located, we can call its Watch method, provided that the corresponding FileProvider provides such monitoring functions. This method accepts a string-type parameter filter. We can use this parameter to specify an expression to filter target directories or files to be monitored. For the predefined fileproviders, only PhysicalFileProvider provides file monitoring. For PhysicalFileProvider, it delegates a FileSystemWatcher object to complete the final file monitoring task. When specifying the deletion expression, we can specify a specific directory or file path to be monitored, or use the wildcard "*" as shown in the following table.
Filter |
Description |
Foobar/data.txt |
Data.txt, a file stored in the directory foobar. |
Foobar/*. txt |
All the. txt files stored in the directory foobar. |
Foobar /*.* |
All files stored in the foobar directory. |
Foobar //*.* |
All files stored in all subdirectories of the foobar directory. |
The return type of the Watch method is the IChangeToken interface defined below. All types of the interface and the corresponding objects are collectively referred to as ChangeToken. ChangeToken can be considered as a token associated with a certain data and sent to the outside when the data changes. If the associated data changes, its HasChanged attribute will become True. We can call its RegisterChangeCallback method to register a callback that can be automatically executed when data changes. It is worth mentioning that this method will return the registered object in the form of an IDisposable object. In principle, we should call its Dispose method to cancel the registration at the appropriate time, to avoid Memory leakage. As for another attribute of the IChangeToken interface, ActiveChangeCallbacks indicates whether to actively perform the registration callback operation when data changes.
1: public interface IChangeToken
2: {
3: bool HasChanged { get; }
4: bool ActiveChangeCallbacks { get; }
5:
6: IDisposable RegisterChangeCallback(Action<object> callback, object state);
7: }
V. Path prefix "/"
In general, whether it is to call the path of the target file and directory specified by the GetFileInfo and GetDirectoryContents methods, or to call the filter expression specified by the Watch method, it is a relative path for the root directory of the current FileProvider. The specified path can use the "/" character as the prefix, but this prefix is unnecessary. In other words, the two groups of programs shown below are completely equivalent.
1: // The path does not contain the prefix "/"
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: // The path contains the prefix "/"
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");
Vi. Summary
In general, FileProvider-centered file systems are very simple in design. In addition to FileProvider, the file system also involves other objects, such as DirectoryContents, FileInfo, and ChangeToken. These objects have corresponding interface definitions, and the UML shown shows the interfaces involved and their relationships.