Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions System.IO.Abstractions/FileStreamFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Security.AccessControl;
using Microsoft.Win32.SafeHandles;

namespace System.IO.Abstractions
{
[Serializable]
internal sealed class FileStreamFactory : IFileStreamFactory
{
public Stream Create(string path, FileMode mode)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a nit, but thought this was interesting.
https://ericlippert.com/2014/09/15/internal-or-public/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 That's a good read, thanks! I also prefer public in these cases, but I could never provide non-subjective reasons for that

=> new FileStream(path, mode);

public Stream Create(string path, FileMode mode, FileAccess access)
=> new FileStream(path, mode, access);

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share)
=> new FileStream(path, mode, access, share);

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
=> new FileStream(path, mode, access, share, bufferSize);

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options)
=> new FileStream(path, mode, access, share, bufferSize, options);

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync)
=> new FileStream(path, mode, access, share, bufferSize, useAsync);

public Stream Create(SafeFileHandle handle, FileAccess access)
=> new FileStream(handle, access);

public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize)
=> new FileStream(handle, access, bufferSize);

public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync)
=> new FileStream(handle, access, bufferSize, isAsync);

#if NET40
public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity)
=> new FileStream(path, mode, rights, share, bufferSize, options, fileSecurity);

public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options)
=> new FileStream(path, mode, rights, share, bufferSize, options);
#endif

#if NET40 || NETSTANDARD_20
[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access)
=> new FileStream(handle, access);

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle)
=> new FileStream(handle, access, ownsHandle);

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize)
=> new FileStream(handle, access, ownsHandle, bufferSize);

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync)
=> new FileStream(handle, access, ownsHandle, bufferSize, isAsync);
#endif
}
}
6 changes: 6 additions & 0 deletions System.IO.Abstractions/FileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public IFileInfoFactory FileInfo
get { return fileInfoFactory ?? (fileInfoFactory = new FileInfoFactory()); }
}

FileStreamFactory fileStreamFactory;
public IFileStreamFactory FileStream
{
get { return fileStreamFactory ?? (fileStreamFactory = new FileStreamFactory()); }
}

PathBase path;
public PathBase Path
{
Expand Down
46 changes: 46 additions & 0 deletions System.IO.Abstractions/IFileStreamFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Security.AccessControl;
using Microsoft.Win32.SafeHandles;

namespace System.IO.Abstractions
{
public interface IFileStreamFactory
{
Stream Create(string path, FileMode mode);

Stream Create(string path, FileMode mode, FileAccess access);

Stream Create(string path, FileMode mode, FileAccess access, FileShare share);

Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize);

Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options);

Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync);

Stream Create(SafeFileHandle handle, FileAccess access);

Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize);

Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync);

#if NET40
Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity);

Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options);
#endif

#if NET40 || NETSTANDARD_20
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the NET40/NETSTANDARD check here? I don't see a mirroring check in the MockFileStreamFactory

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, because the “real” implementation doesn’t support these overloads on NS1.4.

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
Stream Create(IntPtr handle, FileAccess access);

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
Stream Create(IntPtr handle, FileAccess access, bool ownsHandle);

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize);

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync);
#endif
}
}
1 change: 1 addition & 0 deletions System.IO.Abstractions/IFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public interface IFileSystem
FileBase File { get; }
DirectoryBase Directory { get; }
IFileInfoFactory FileInfo { get; }
IFileStreamFactory FileStream { get; }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my only concern. Since we're adding onto IFileSystem, it's a breaking change.. but is anyone really writing their own classes using IFileSystem?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, same goes for 07227bc... I also don't think this will be a big problem for people. Whenever we are done with the old issues/PRs we should again think about release strategy, versioning, issue tagging, etc...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear. I would merge this one and as a follow-up take care about our future strategy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I would agree. It's probably an incredibly small subset of users it would impact.

PathBase Path { get; }
IDirectoryInfoFactory DirectoryInfo { get; }
IDriveInfoFactory DriveInfo { get; }
Expand Down
2 changes: 1 addition & 1 deletion System.IO.Abstractions/System.IO.Abstractions.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net40;netstandard1.4;netstandard2.0;</TargetFrameworks>
Expand Down
14 changes: 0 additions & 14 deletions System.IO.Abstractions/System.IO.Abstractions.nuspec

This file was deleted.

45 changes: 45 additions & 0 deletions TestHelpers.Tests/MockFileStreamFactoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Collections.Generic;
using NUnit.Framework;

namespace System.IO.Abstractions.TestingHelpers.Tests
{
[TestFixture]
public class MockFileStreamFactoryTests
{
[Test]
[TestCase(FileMode.Create)]
[TestCase(FileMode.Append)]
public void MockFileStreamFactory_CreateForExistingFile_ShouldReturnStream(FileMode fileMode)
{
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ @"c:\existing.txt", MockFileData.NullObject }
});

var fileStreamFactory = new MockFileStreamFactory(fileSystem);

// Act
var result = fileStreamFactory.Create(@"c:\existing.txt", fileMode);

// Assert
Assert.IsNotNull(result);
}

[Test]
[TestCase(FileMode.Create)]
[TestCase(FileMode.Append)]
public void MockFileStreamFactory_CreateForNonExistingFile_ShouldReturnStream(FileMode fileMode)
{
// Arrange
var fileSystem = new MockFileSystem();
var fileStreamFactory = new MockFileStreamFactory(fileSystem);

// Act
var result = fileStreamFactory.Create(@"c:\not_existing.txt", fileMode);

// Assert
Assert.IsNotNull(result);
}
}
}
83 changes: 83 additions & 0 deletions TestingHelpers/MockFileStreamFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System.Security.AccessControl;
using Microsoft.Win32.SafeHandles;

namespace System.IO.Abstractions.TestingHelpers
{
[Serializable]
public class MockFileStreamFactory : IFileStreamFactory
{
private readonly IMockFileDataAccessor mockFileSystem;

public MockFileStreamFactory(IMockFileDataAccessor mockFileSystem)
=> this.mockFileSystem = mockFileSystem ?? throw new ArgumentNullException(nameof(mockFileSystem));

public Stream Create(string path, FileMode mode)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode));

public Stream Create(string path, FileMode mode, FileAccess access)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode, access));

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode, access));

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode, access));

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode, access));

public Stream Create(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode, access));

#if NET40
public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode));

public Stream Create(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options)
=> new MockFileStream(mockFileSystem, path, GetStreamType(mode));
#endif

#if NET40 || NETSTANDARD_20
[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access)
=> new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access));

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle)
=> new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access));

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize)
=> new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access));

[Obsolete("This method has been deprecated. Please use new Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
public Stream Create(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync)
=> new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access));
#endif

public Stream Create(SafeFileHandle handle, FileAccess access)
=> new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access));

public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize)
=> new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access));

public Stream Create(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync)
=> new MockFileStream(mockFileSystem, handle.ToString(), GetStreamType(FileMode.Append, access));

private static MockFileStream.StreamType GetStreamType(FileMode mode, FileAccess access = FileAccess.ReadWrite)
{
if (access == FileAccess.Read)
{
return MockFileStream.StreamType.READ;
}
else if (mode == FileMode.Append)
{
return MockFileStream.StreamType.APPEND;
}
else
{
return MockFileStream.StreamType.WRITE;
}
}
}
}
5 changes: 4 additions & 1 deletion TestingHelpers/MockFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace System.IO.Abstractions.TestingHelpers
public class MockFileSystem : IFileSystem, IMockFileDataAccessor
{
private readonly IDictionary<string, MockFileData> files;

[NonSerialized]
private readonly PathVerifier pathVerifier;

Expand All @@ -26,10 +25,12 @@ public MockFileSystem(IDictionary<string, MockFileData> files, string currentDir
pathVerifier = new PathVerifier(this);

this.files = new Dictionary<string, MockFileData>(StringComparer.OrdinalIgnoreCase);

Path = new MockPath(this);
File = new MockFile(this);
Directory = new MockDirectory(this, File, currentDirectory);
FileInfo = new MockFileInfoFactory(this);
FileStream = new MockFileStreamFactory(this);
DirectoryInfo = new MockDirectoryInfoFactory(this);
DriveInfo = new MockDriveInfoFactory(this);
FileSystemWatcher = new MockFileSystemWatcherFactory();
Expand All @@ -49,6 +50,8 @@ public MockFileSystem(IDictionary<string, MockFileData> files, string currentDir

public IFileInfoFactory FileInfo { get; }

public IFileStreamFactory FileStream { get; }

public PathBase Path { get; }

public IDirectoryInfoFactory DirectoryInfo { get; }
Expand Down
2 changes: 1 addition & 1 deletion TestingHelpers/TestingHelpers.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;netstandard1.4;netstandard2.0;</TargetFrameworks>
<PackageId>System.IO.Abstractions.TestingHelpers</PackageId>
Expand Down