未验证 提交 8aba1868 编写于 作者: E Emmanuel André 提交者: GitHub

Implement IDirectoryContents on PhysicalDirectoryInfo (#91024)

* Implement IDirectoryContents on PhysicalDirectoryInfo

* Update test

* Avoid code duplication
上级 431ac21a
...@@ -43,7 +43,7 @@ public enum ExclusionFilters ...@@ -43,7 +43,7 @@ public enum ExclusionFilters
System = 4, System = 4,
Sensitive = 7, Sensitive = 7,
} }
public partial class PhysicalDirectoryInfo : Microsoft.Extensions.FileProviders.IFileInfo public partial class PhysicalDirectoryInfo : Microsoft.Extensions.FileProviders.IFileInfo, Microsoft.Extensions.FileProviders.IDirectoryContents, System.Collections.Generic.IEnumerable<Microsoft.Extensions.FileProviders.IFileInfo>, System.Collections.IEnumerable
{ {
public PhysicalDirectoryInfo(System.IO.DirectoryInfo info) { } public PhysicalDirectoryInfo(System.IO.DirectoryInfo info) { }
public bool Exists { get { throw null; } } public bool Exists { get { throw null; } }
...@@ -53,6 +53,8 @@ public partial class PhysicalDirectoryInfo : Microsoft.Extensions.FileProviders. ...@@ -53,6 +53,8 @@ public partial class PhysicalDirectoryInfo : Microsoft.Extensions.FileProviders.
public string Name { get { throw null; } } public string Name { get { throw null; } }
public string PhysicalPath { get { throw null; } } public string PhysicalPath { get { throw null; } }
public System.IO.Stream CreateReadStream() { throw null; } public System.IO.Stream CreateReadStream() { throw null; }
public System.Collections.Generic.IEnumerator<IFileInfo> GetEnumerator() { throw null; }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
} }
public partial class PhysicalFileInfo : Microsoft.Extensions.FileProviders.IFileInfo public partial class PhysicalFileInfo : Microsoft.Extensions.FileProviders.IFileInfo
{ {
......
...@@ -4,9 +4,7 @@ ...@@ -4,9 +4,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq;
using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.FileProviders.Physical;
namespace Microsoft.Extensions.FileProviders.Internal namespace Microsoft.Extensions.FileProviders.Internal
...@@ -16,9 +14,7 @@ namespace Microsoft.Extensions.FileProviders.Internal ...@@ -16,9 +14,7 @@ namespace Microsoft.Extensions.FileProviders.Internal
/// </summary> /// </summary>
public class PhysicalDirectoryContents : IDirectoryContents public class PhysicalDirectoryContents : IDirectoryContents
{ {
private IEnumerable<IFileInfo>? _entries; private readonly PhysicalDirectoryInfo _info;
private readonly string _directory;
private readonly ExclusionFilters _filters;
/// <summary> /// <summary>
/// Initializes an instance of <see cref="PhysicalDirectoryContents"/> /// Initializes an instance of <see cref="PhysicalDirectoryContents"/>
...@@ -37,52 +33,14 @@ public PhysicalDirectoryContents(string directory, ExclusionFilters filters) ...@@ -37,52 +33,14 @@ public PhysicalDirectoryContents(string directory, ExclusionFilters filters)
{ {
ThrowHelper.ThrowIfNull(directory); ThrowHelper.ThrowIfNull(directory);
_directory = directory; _info = new PhysicalDirectoryInfo(new DirectoryInfo(directory), filters);
_filters = filters;
} }
/// <inheritdoc /> /// <inheritdoc/>
public bool Exists => Directory.Exists(_directory); public bool Exists => _info.Exists;
/// <inheritdoc /> /// <inheritdoc/>
public IEnumerator<IFileInfo> GetEnumerator() public IEnumerator<IFileInfo> GetEnumerator() => _info.GetEnumerator();
{ IEnumerator IEnumerable.GetEnumerator() => _info.GetEnumerator();
EnsureInitialized();
return _entries.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
EnsureInitialized();
return _entries.GetEnumerator();
}
[MemberNotNull(nameof(_entries))]
private void EnsureInitialized()
{
try
{
_entries = new DirectoryInfo(_directory)
.EnumerateFileSystemInfos()
.Where(info => !FileSystemInfoHelper.IsExcluded(info, _filters))
.Select<FileSystemInfo, IFileInfo>(info =>
{
if (info is FileInfo file)
{
return new PhysicalFileInfo(file);
}
else if (info is DirectoryInfo dir)
{
return new PhysicalDirectoryInfo(dir);
}
// shouldn't happen unless BCL introduces new implementation of base type
throw new InvalidOperationException(SR.UnexpectedFileSystemInfo);
});
}
catch (Exception ex) when (ex is DirectoryNotFoundException || ex is IOException)
{
_entries = Enumerable.Empty<IFileInfo>();
}
}
} }
} }
...@@ -2,16 +2,22 @@ ...@@ -2,16 +2,22 @@
// The .NET Foundation licenses this file to you under the MIT license. // The .NET Foundation licenses this file to you under the MIT license.
using System; using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq;
namespace Microsoft.Extensions.FileProviders.Physical namespace Microsoft.Extensions.FileProviders.Physical
{ {
/// <summary> /// <summary>
/// Represents a directory on a physical filesystem /// Represents a directory on a physical filesystem
/// </summary> /// </summary>
public class PhysicalDirectoryInfo : IFileInfo public class PhysicalDirectoryInfo : IFileInfo, IDirectoryContents
{ {
private readonly DirectoryInfo _info; private readonly DirectoryInfo _info;
private IEnumerable<IFileInfo>? _entries;
private readonly ExclusionFilters _filters;
/// <summary> /// <summary>
/// Initializes an instance of <see cref="PhysicalDirectoryInfo"/> that wraps an instance of <see cref="System.IO.DirectoryInfo"/> /// Initializes an instance of <see cref="PhysicalDirectoryInfo"/> that wraps an instance of <see cref="System.IO.DirectoryInfo"/>
...@@ -22,6 +28,12 @@ public PhysicalDirectoryInfo(DirectoryInfo info) ...@@ -22,6 +28,12 @@ public PhysicalDirectoryInfo(DirectoryInfo info)
_info = info; _info = info;
} }
internal PhysicalDirectoryInfo(DirectoryInfo info, ExclusionFilters filters)
{
_info = info;
_filters = filters;
}
/// <inheritdoc /> /// <inheritdoc />
public bool Exists => _info.Exists; public bool Exists => _info.Exists;
...@@ -55,5 +67,40 @@ public Stream CreateReadStream() ...@@ -55,5 +67,40 @@ public Stream CreateReadStream()
{ {
throw new InvalidOperationException(SR.CannotCreateStream); throw new InvalidOperationException(SR.CannotCreateStream);
} }
/// <inheritdoc/>
public IEnumerator<IFileInfo> GetEnumerator()
{
EnsureInitialized();
return _entries.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
EnsureInitialized();
return _entries.GetEnumerator();
}
[MemberNotNull(nameof(_entries))]
private void EnsureInitialized()
{
try
{
_entries = _info
.EnumerateFileSystemInfos()
.Where(info => !FileSystemInfoHelper.IsExcluded(info, _filters))
.Select<FileSystemInfo, IFileInfo>(info => info switch
{
FileInfo file => new PhysicalFileInfo(file),
DirectoryInfo dir => new PhysicalDirectoryInfo(dir),
// shouldn't happen unless BCL introduces new implementation of base type
_ => throw new InvalidOperationException(SR.UnexpectedFileSystemInfo)
});
}
catch (Exception ex) when (ex is DirectoryNotFoundException or IOException)
{
_entries = Enumerable.Empty<IFileInfo>();
}
}
} }
} }
...@@ -663,15 +663,39 @@ public void GetDirectoryContentsReturnsRootDirectoryContentsForEmptyPath() ...@@ -663,15 +663,39 @@ public void GetDirectoryContentsReturnsRootDirectoryContentsForEmptyPath()
{ {
using (var root = new TempDirectory(GetTestFilePath())) using (var root = new TempDirectory(GetTestFilePath()))
{ {
File.Create(Path.Combine(root.Path, "File" + Guid.NewGuid().ToString())); string fileName = "File" + Guid.NewGuid().ToString();
Directory.CreateDirectory(Path.Combine(root.Path, "Dir" + Guid.NewGuid().ToString())); string subDirectoryName = "Dir" + Guid.NewGuid().ToString();
root.CreateFile(fileName);
root.CreateFolder(subDirectoryName);
root.CreateFile(Path.Combine(subDirectoryName, fileName));
using (var provider = new PhysicalFileProvider(root.Path)) using (var provider = new PhysicalFileProvider(root.Path))
{ {
var contents = provider.GetDirectoryContents(string.Empty); var contents = provider.GetDirectoryContents(string.Empty);
Assert.Collection(contents.OrderBy(c => c.Name), Assert.Collection(contents.OrderBy(c => c.Name),
item => Assert.IsType<PhysicalDirectoryInfo>(item), item =>
item => Assert.IsType<PhysicalFileInfo>(item)); {
// Directory
Assert.True(item.Exists);
Assert.Equal(subDirectoryName, item.Name);
Assert.True(item.IsDirectory);
var directory = Assert.IsAssignableFrom<IDirectoryContents>(item);
Assert.True(directory.Exists);
// Single file in directory
var file = Assert.Single(directory);
Assert.True(file.Exists);
Assert.Equal(fileName, file.Name);
Assert.False(file.IsDirectory);
Assert.False(file is IDirectoryContents);
},
item =>
{
// File
Assert.True(item.Exists);
Assert.Equal(fileName, item.Name);
Assert.False(item.IsDirectory);
Assert.False(item is IDirectoryContents);
});
} }
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册