-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement IDirectoryContents on PhysicalDirectoryInfo #91024
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @dotnet/area-extensions-filesystem Issue DetailsCloses #86354 Also introduces a refactoring of the internal (but publicly exposed)
|
Other providers also have it implemented, that the IFileInfo representing a directory does not implement IDirectoryContents. |
@rameel can you please elaborate? Are you saying that other IFileInfo implementations that represent a directory need to also be changed? |
{ | ||
try | ||
{ | ||
_entries = _info |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this change but what's the point of _entries
if we assign it every time it will be used?
Yes, I think the same approach should be applied to other providers as well. This would ensure consistent behavior and adhere to the principle of least astonishment. Since Currently, the way it's implemented in this pull request, if it keeps as it is, we can't rely on the same code to work correctly when given different implementations of public static void Work(IFileProvider provider) Ideally, I believe this should be reflected in the interface, something like this: public interface IDirectoryContents : IFileInfo This way, the code working with However, this would be a breaking change, and I'm not sure if it's the right approach to introduce it. But if similar changes are made to other official providers, where |
@rameel I don't think this is worth introducing a breaking change. One way in which we could make this work is by introducing
Bear in mind that we don't own all types that extend cc @vpenades |
Sounds good. |
I think the current PR is fine and there's no need for an IDirectoryInfo interface. I think the best approach to consume these interfaces is this:
Notice that what really defines an instance as a directory view is the instance implementing IDirectoryContents, having a bool IsDirectory property is just sugar. Also notice that in more advanced scenarios like some I've seen around, it can happen that an actual file can implement IDirectoryContents, for example, consider a Zip archive, that is a file itself, but contains a full directory tree inside. Having a decoupled IFileInfo and a IDirectoryContents interfaces allows to combining them in some of these advanced scenarios, that's why I think IDirectoryInfo is not neccesary because it is restricted to a specific scenario (physical direrctories) |
@rameel I also think the proposed abstraction should suffice for most scenarios. |
Another option is to reject the proposal, PhysicalDirectoryInfo is not sealed so you can actually achieve content enumeration by doing the following: class EnumerablePhysicalDirectoryInfo : PhysicalDirectoryInfo, IDirectoryContents
{
public MyPhysicalDirectoryInfo(DirectoryInfo info) : base(info)
{
}
public IEnumerator<IFileInfo> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
} @vpenades can you remind me why is it important for you to address this in PhysicalDirectoryInfo? |
The whole point is to not have to require using the PhysicalDirectoryInfo directly for directory traversal. Think about it: if you have access to Historically there's been a problem with The new In fact, trying to solve issues like these by requiring to use the implementing class is big anti-pattern. |
But as I shown in #91024 (comment) the building blocks for directory enumeration are already there. So we are really not achieving much in this PR, don't you think? |
Let's say I write a library that is able to display a directory tree in WPF, and I want it to work on physical drives, emulated physical drives in memory, directories inside archives, remote directories over a REST API or whatever crazy directory tree system I want to traverse. Lets call the library First thing: which packages should this library reference? since it's a generic directory tree traversing library, it only requires Microsoft.Extensions.FileProviders.Abstractions and nothing else, right? So I could use the control like this: WPFDirectoryTreePanel.Root = (IFileProvider)new PhysicalFileProvider("c:\\"); but also like this: WPFDirectoryTreePanel.Root = (IFileProvider)new VirtualFileProvider(...);
WPFDirectoryTreePanel.Root = (IFileProvider)new ArchiveFileProvider("archive.ZIP"); Notice that the WPF control is not referencing If traversing trees with the interface APIs is limited to only the first directory level, then the whole IFileInfo abstraction is flawed, because to develop such a tree view control, you should not only require to implement a specific hack for PhysicalDirectoryInfo, but for all IFileInfo implementations out there. |
Doing a search, I've found other people has reached the same conclusion that an instance representing a directory must implement both IFileInfo and IDirectoryContents |
Yes, I understand, I'm not trying to force
That is good data that supports that this change will leave us in a better state, thanks. |
But what about other providers? |
@rameel could you please file issues on the repos where you think other |
About other providers, I was considering .Embedded , but I can't find it anymore, it's been removed? Anyway that provider is a bit special since embedded resources use the "." dot as separator, which is a bit tricky to use when using with files with multi dotted extensions... |
Embedded file provider is still there https://learn.microsoft.com/dotnet/api/microsoft.extensions.fileproviders.embeddedfileprovider. It only contains a |
There is a I have looked at the implementations of other providers we have, and no changes are needed there because:
|
@rameel thanks for checking, would you like to send a PR to address ManifestDirectoryInfo? I missed it because I wrongfully checked public types only. |
I apologize, I was sure that |
I have submitted a PR #50586 |
Closes #86354
Also introduces a refactoring of the internal (but publicly exposed)
PhysicalDirectoryContents
class, in order to avoid code duplication.