diff --git a/PCLExt.FileStorage.sln b/PCLExt.FileStorage.sln
index 88de1c2..c552ffb 100644
--- a/PCLExt.FileStorage.sln
+++ b/PCLExt.FileStorage.sln
@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage", "src\PCLExt.FileStorage\PCLExt.FileStorage.csproj", "{A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage.Portable", "src\PCLExt.FileStorage.Portable\PCLExt.FileStorage.Portable.csproj", "{A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage.Abstractions", "src\PCLExt.FileStorage.Abstractions\PCLExt.FileStorage.Abstractions.csproj", "{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage.Portable.Abstractions", "src\PCLExt.FileStorage.Portable.Abstractions\PCLExt.FileStorage.Portable.Abstractions.csproj", "{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage.Desktop", "src\PCLExt.FileStorage.Desktop\PCLExt.FileStorage.Desktop.csproj", "{54DBACEB-B898-494B-AD88-2A407CB55A5A}"
EndProject
@@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage.iOS", "s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage.Mac", "src\PCLExt.FileStorage.Mac\PCLExt.FileStorage.Mac.csproj", "{0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLExt.FileStorage.Core", "src\PCLExt.FileStorage.Core\PCLExt.FileStorage.Core.csproj", "{94E4FE17-7F2B-4623-8FFA-12F4056CCB2A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AppStore|Any CPU = AppStore|Any CPU
@@ -22,18 +24,12 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {03DA3968-61A3-44D1-9F99-F55D31E07813}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU
- {03DA3968-61A3-44D1-9F99-F55D31E07813}.AppStore|Any CPU.Build.0 = AppStore|Any CPU
- {03DA3968-61A3-44D1-9F99-F55D31E07813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {03DA3968-61A3-44D1-9F99-F55D31E07813}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {03DA3968-61A3-44D1-9F99-F55D31E07813}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {03DA3968-61A3-44D1-9F99-F55D31E07813}.Release|Any CPU.Build.0 = Release|Any CPU
- {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
- {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.AppStore|Any CPU.Build.0 = Release|Any CPU
- {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Release|Any CPU.Build.0 = Release|Any CPU
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}.AppStore|Any CPU.Build.0 = Release|Any CPU
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -52,12 +48,24 @@ Global
{8EFC0559-3C9C-4D0C-A5A5-579E58FFE621}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EFC0559-3C9C-4D0C-A5A5-579E58FFE621}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EFC0559-3C9C-4D0C-A5A5-579E58FFE621}.Release|Any CPU.Build.0 = Release|Any CPU
- {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
- {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.AppStore|Any CPU.Build.0 = Release|Any CPU
- {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A7C97A2B-F996-4CAF-87D8-F3A60B2B4D44}.Release|Any CPU.Build.0 = Release|Any CPU
+ {03DA3968-61A3-44D1-9F99-F55D31E07813}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU
+ {03DA3968-61A3-44D1-9F99-F55D31E07813}.AppStore|Any CPU.Build.0 = AppStore|Any CPU
+ {03DA3968-61A3-44D1-9F99-F55D31E07813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {03DA3968-61A3-44D1-9F99-F55D31E07813}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {03DA3968-61A3-44D1-9F99-F55D31E07813}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {03DA3968-61A3-44D1-9F99-F55D31E07813}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0B02DE9A-C3C5-4DB9-B87F-6B05C3566946}.Release|Any CPU.Build.0 = Release|Any CPU
+ {94E4FE17-7F2B-4623-8FFA-12F4056CCB2A}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {94E4FE17-7F2B-4623-8FFA-12F4056CCB2A}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {94E4FE17-7F2B-4623-8FFA-12F4056CCB2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {94E4FE17-7F2B-4623-8FFA-12F4056CCB2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {94E4FE17-7F2B-4623-8FFA-12F4056CCB2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {94E4FE17-7F2B-4623-8FFA-12F4056CCB2A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs
index e4944f5..12e9aab 100644
--- a/common/CommonAssemblyInfo.cs
+++ b/common/CommonAssemblyInfo.cs
@@ -3,9 +3,9 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PCLExt.FileStorage")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyCopyright("Copyright © 2016-2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("1.1.3.0")]
-[assembly: AssemblyFileVersion("1.1.3.0")]
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/common/PCLExt.FileStorage.nuspec b/common/PCLExt.FileStorage.nuspec
index 962482b..c36651c 100644
--- a/common/PCLExt.FileStorage.nuspec
+++ b/common/PCLExt.FileStorage.nuspec
@@ -2,7 +2,7 @@
PCLExt.FileStorage
- 1.1.3.0
+ 1.2.0.0
PCL Extension - File Storage API
Daniel Plaisted,Aragas
Aragas
@@ -10,30 +10,37 @@
https://github.com/Aragas/PCLExt.FileStorage
https://raw.githubusercontent.com/Aragas/PCLExt.FileStorage/master/common/sushi_64.png
false
- PCL Extension provides file system implementations for PCL, .NET, Xamarin.iOS, Xamarin.Android and Xamarin.Mac. This makes it easier to create cross-platform .NET libraries and apps.
+ PCL Extension provides file system implementations for PCL, .NET, Xamarin.iOS, Xamarin.Android and Xamarin.Mac. This makes it easier to create cross-platform .NET libraries and apps. Supports .NET Standard now.
PCL Extension provides file system implementations for PCL platform
- io storage file system portable pcl android mac ios xamarin monoandroid monotouch
+ io storage file system portable pcl android mac ios xamarin monoandroid monotouch core netcore netstandard
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Abstractions/IFileSystem.cs b/src/PCLExt.FileStorage.Abstractions/IFileSystem.cs
deleted file mode 100644
index f7036f8..0000000
--- a/src/PCLExt.FileStorage.Abstractions/IFileSystem.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-//-----------------------------------------------------------------------
-//
-// Copyright (c) Daniel Plaisted. All rights reserved.
-//
-// This file is a derivation of:
-// https://github.com/dsplaisted/PCLStorage
-// Which is released under the MS-PL license.
-//-----------------------------------------------------------------------
-
-namespace PCLExt.FileStorage
-{
- ///
- /// Represents a file system.
- ///
- public interface IFileSystem
- {
- ///
- /// A folder representing storage which is where the app is running.
- ///
- IFolder BaseStorage { get; }
- ///
- /// A folder representing storage which is local to the current device.
- ///
- IFolder LocalStorage { get; }
- ///
- /// A folder representing storage which may be synced with other devices for the same user.
- ///
- IFolder RoamingStorage { get; }
- ///
- /// Depending on OS, it will return BaseStorage on Desktop platforms and LocalStorage on Mobile platforms.
- ///
- IFolder SpecialStorage { get; }
- }
-}
diff --git a/src/PCLExt.FileStorage.Android/PCLExt.FileStorage.Android.csproj b/src/PCLExt.FileStorage.Android/PCLExt.FileStorage.Android.csproj
index c972a28..bae5917 100644
--- a/src/PCLExt.FileStorage.Android/PCLExt.FileStorage.Android.csproj
+++ b/src/PCLExt.FileStorage.Android/PCLExt.FileStorage.Android.csproj
@@ -37,44 +37,84 @@
-
-
-
+
Properties\CommonAssemblyInfo.cs
-
- DesktopFileSystem.cs
+
+ NET4FileImplementation.cs
-
- FileSystemFile.cs
+
+ NET4FolderImplementation.cs
-
- FileSystemFolder.cs
+
+ BaseFile.cs
-
- AwaitExtensions.cs
+
+ BaseFolder.cs
-
- PortablePath.cs
+
+ CreationCollisionOption.cs
-
- Requires.cs
+
+ ExistenceCheckResult.cs
-
- BaseFolder.cs
+
+ FolderSearchOption.cs
-
- BaseFile.cs
+
+ IFile.cs
-
-
- FileSystem.cs
+
+ IFolder.cs
+
+
+ NameCollisionOption.cs
+
+
+ Exceptions\DirectoryNotFoundException.cs
+
+
+ Exceptions\ExceptionsHelper.cs
+
+
+ Exceptions\FileNotFoundException.cs
+
+
+ Extensions\AwaitExtensions.cs
+
+ Extensions\FileExtensions.cs
+
+
+ Extensions\FolderExtensions.cs
+
+
+ Files\FileFromPath.cs
+
+
+ Folders\ApplicationFolder.cs
+
+
+ Folders\FolderFromPath.cs
+
+
+ Folders\LocalFolder.cs
+
+
+ Folders\RoamingFolder.cs
+
+
+ PortablePath.cs
+
+
+ Requires.cs
+
+
-
+
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}
PCLExt.FileStorage.Abstractions
diff --git a/src/PCLExt.FileStorage.Core/NETCOREFileImplementation.cs b/src/PCLExt.FileStorage.Core/NETCOREFileImplementation.cs
new file mode 100644
index 0000000..5400d50
--- /dev/null
+++ b/src/PCLExt.FileStorage.Core/NETCOREFileImplementation.cs
@@ -0,0 +1,252 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Daniel Plaisted. All rights reserved.
+//
+// This file is a derivation of:
+// https://github.com/dsplaisted/PCLStorage
+// Which is released under the MS-PL license.
+//-----------------------------------------------------------------------
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+using PCLExt.FileStorage.Extensions;
+
+namespace PCLExt.FileStorage
+{
+ ///
+ /// Represents a file in the .
+ ///
+ [DebuggerDisplay("Name = {" + nameof(Name) + "}")]
+ internal class NETCOREFileImplementation : IFile
+ {
+ ///
+ public string Name { get; private set; }
+ ///
+ public string Path { get; private set; }
+
+ ///
+ /// Creates a new corresponding to the specified path.
+ ///
+ /// The file path
+ public NETCOREFileImplementation(string path)
+ {
+ Name = System.IO.Path.GetFileName(path);
+ Path = path;
+ }
+
+ ///
+ public Stream Open(FileAccess fileAccess)
+ {
+ if (fileAccess == FileAccess.Read)
+ return File.OpenRead(Path);
+ else if (fileAccess == FileAccess.ReadAndWrite)
+ return File.Open(Path, FileMode.Open, System.IO.FileAccess.ReadWrite);
+ else
+ throw new ArgumentException($"Unrecognized FileAccess value: {fileAccess}");
+ }
+ ///
+ public async Task OpenAsync(FileAccess fileAccess, CancellationToken cancellationToken)
+ {
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ if (fileAccess == FileAccess.Read)
+ return File.OpenRead(Path);
+ else if (fileAccess == FileAccess.ReadAndWrite)
+ return File.Open(Path, FileMode.Open, System.IO.FileAccess.ReadWrite);
+ else
+ throw new ArgumentException($"Unrecognized FileAccess value: {fileAccess}");
+ }
+
+ ///
+ public void Delete()
+ {
+ if (!File.Exists(Path))
+ throw new FileNotFoundException($"File does not exist: {Path}");
+
+ File.Delete(Path);
+ }
+ ///
+ public async Task DeleteAsync(CancellationToken cancellationToken)
+ {
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ if (!File.Exists(Path))
+ throw new FileNotFoundException($"File does not exist: {Path}");
+
+ File.Delete(Path);
+ }
+
+ ///
+ public void Rename(string newName, NameCollisionOption collisionOption)
+ {
+ Requires.NotNullOrEmpty(newName, "newName");
+
+ Move(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Path), newName), collisionOption);
+ }
+ ///
+ public async Task RenameAsync(string newName, NameCollisionOption collisionOption, CancellationToken cancellationToken)
+ {
+ Requires.NotNullOrEmpty(newName, "newName");
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ await MoveAsync(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Path), newName), collisionOption, cancellationToken);
+ }
+
+ ///
+ public void Move(string newPath, NameCollisionOption collisionOption)
+ {
+ Requires.NotNullOrEmpty(newPath, "newPath");
+
+ var newDirectory = System.IO.Path.GetDirectoryName(newPath);
+ var newName = System.IO.Path.GetFileName(newPath);
+
+ for (var counter = 1; ; counter++)
+ {
+ var candidateName = newName;
+ if (counter > 1)
+ candidateName = $"{System.IO.Path.GetFileNameWithoutExtension(newName)} ({counter}){System.IO.Path.GetExtension(newName)}";
+
+ var candidatePath = System.IO.Path.Combine(newDirectory, candidateName);
+
+ if (File.Exists(candidatePath))
+ {
+ switch (collisionOption)
+ {
+ case NameCollisionOption.FailIfExists:
+ throw new IOException("File already exists.");
+ case NameCollisionOption.GenerateUniqueName:
+ continue; // try again with a new name.
+ case NameCollisionOption.ReplaceExisting:
+ File.Delete(candidatePath);
+ break;
+ }
+ }
+
+ File.Move(Path, candidatePath);
+ Path = candidatePath;
+ Name = candidateName;
+ return;
+ }
+ }
+ ///
+ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, CancellationToken cancellationToken)
+ {
+ Requires.NotNullOrEmpty(newPath, "newPath");
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ var newDirectory = System.IO.Path.GetDirectoryName(newPath);
+ var newName = System.IO.Path.GetFileName(newPath);
+
+ for (var counter = 1; ; counter++)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ var candidateName = newName;
+ if (counter > 1)
+ candidateName = $"{System.IO.Path.GetFileNameWithoutExtension(newName)} ({counter}){System.IO.Path.GetExtension(newName)}";
+
+ var candidatePath = System.IO.Path.Combine(newDirectory, candidateName);
+
+ if (File.Exists(candidatePath))
+ {
+ switch (collisionOption)
+ {
+ case NameCollisionOption.FailIfExists:
+ throw new IOException("File already exists.");
+ case NameCollisionOption.GenerateUniqueName:
+ continue; // try again with a new name.
+ case NameCollisionOption.ReplaceExisting:
+ File.Delete(candidatePath);
+ break;
+ }
+ }
+
+ File.Move(Path, candidatePath);
+ Path = candidatePath;
+ Name = candidateName;
+ return;
+ }
+ }
+
+ ///
+ public void Copy(string newPath, NameCollisionOption collisionOption)
+ {
+ Requires.NotNullOrEmpty(newPath, "newPath");
+
+ var newDirectory = System.IO.Path.GetDirectoryName(newPath);
+ var newName = System.IO.Path.GetFileName(newPath);
+
+ for (var counter = 1; ; counter++)
+ {
+ var candidateName = newName;
+ if (counter > 1)
+ candidateName = $"{System.IO.Path.GetFileNameWithoutExtension(newName)} ({counter}){System.IO.Path.GetExtension(newName)}";
+
+ var candidatePath = System.IO.Path.Combine(newDirectory, candidateName);
+
+ if (File.Exists(candidatePath))
+ {
+ switch (collisionOption)
+ {
+ case NameCollisionOption.FailIfExists:
+ throw new IOException("File already exists.");
+ case NameCollisionOption.GenerateUniqueName:
+ continue; // try again with a new name.
+ case NameCollisionOption.ReplaceExisting:
+ File.Delete(candidatePath);
+ break;
+ }
+ }
+
+ File.Copy(Path, candidatePath);
+ Path = candidatePath;
+ Name = candidateName;
+ return;
+ }
+ }
+ ///
+ public async Task CopyAsync(string newPath, NameCollisionOption collisionOption, CancellationToken cancellationToken)
+ {
+ Requires.NotNullOrEmpty(newPath, "newPath");
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ var newDirectory = System.IO.Path.GetDirectoryName(newPath);
+ var newName = System.IO.Path.GetFileName(newPath);
+
+ for (var counter = 1; ; counter++)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ var candidateName = newName;
+ if (counter > 1)
+ candidateName = $"{System.IO.Path.GetFileNameWithoutExtension(newName)} ({counter}){System.IO.Path.GetExtension(newName)}";
+
+ var candidatePath = System.IO.Path.Combine(newDirectory, candidateName);
+
+ if (File.Exists(candidatePath))
+ {
+ switch (collisionOption)
+ {
+ case NameCollisionOption.FailIfExists:
+ throw new IOException("File already exists.");
+ case NameCollisionOption.GenerateUniqueName:
+ continue; // try again with a new name.
+ case NameCollisionOption.ReplaceExisting:
+ File.Delete(candidatePath);
+ break;
+ }
+ }
+
+ File.Copy(Path, candidatePath);
+ Path = candidatePath;
+ Name = candidateName;
+ return;
+ }
+ }
+ }
+}
diff --git a/src/PCLExt.FileStorage.Core/NETCOREFolderImplementation.cs b/src/PCLExt.FileStorage.Core/NETCOREFolderImplementation.cs
new file mode 100644
index 0000000..8514e0c
--- /dev/null
+++ b/src/PCLExt.FileStorage.Core/NETCOREFolderImplementation.cs
@@ -0,0 +1,386 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Daniel Plaisted. All rights reserved.
+//
+// This file is a derivation of:
+// https://github.com/dsplaisted/PCLStorage
+// Which is released under the MS-PL license.
+//-----------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using PCLExt.FileStorage.Extensions;
+
+namespace PCLExt.FileStorage
+{
+ ///
+ /// Represents a folder in the .
+ ///
+ [DebuggerDisplay("Name = {" + nameof(Name) + "}")]
+ internal class NETCOREFolderImplementation : IFolder
+ {
+ private readonly bool _canDelete;
+
+ ///
+ public string Name { get; }
+ ///
+ public string Path { get; }
+
+ ///
+ /// Creates a new corresponding to a specified path.
+ ///
+ /// The folder path.
+ /// Specifies whether the folder can be deleted (via ).
+ public NETCOREFolderImplementation(string path, bool canDelete = false) { Name = System.IO.Path.GetFileName(path); Path = path; _canDelete = canDelete; }
+
+ ///
+ public IFile CreateFile(string desiredName, CreationCollisionOption option)
+ {
+ Requires.NotNullOrEmpty(desiredName, nameof(desiredName));
+
+ EnsureExists();
+
+ var nameToUse = desiredName;
+ var newPath = System.IO.Path.Combine(Path, nameToUse);
+ if (File.Exists(newPath))
+ {
+ if (option == CreationCollisionOption.GenerateUniqueName)
+ {
+ var desiredRoot = System.IO.Path.GetFileNameWithoutExtension(desiredName);
+ var desiredExtension = System.IO.Path.GetExtension(desiredName);
+ for (var num = 2; File.Exists(newPath); num++)
+ {
+ nameToUse = $"{desiredRoot} ({num}){desiredExtension}";
+ newPath = System.IO.Path.Combine(Path, nameToUse);
+ }
+ InternalCreateFile(newPath);
+ }
+ else if (option == CreationCollisionOption.ReplaceExisting)
+ {
+ File.Delete(newPath);
+ InternalCreateFile(newPath);
+ }
+ else if (option == CreationCollisionOption.FailIfExists)
+ throw new IOException($"File already exists: {newPath}");
+ else if (option == CreationCollisionOption.OpenIfExists)
+ {
+ // No operation.
+ }
+ else
+ throw new ArgumentException($"Unrecognized CreationCollisionOption: {option}");
+ }
+ else
+ {
+ // Create file.
+ InternalCreateFile(newPath);
+ }
+
+ return new NETCOREFileImplementation(newPath);
+ }
+ ///
+ public async Task CreateFileAsync(string desiredName, CreationCollisionOption option, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ Requires.NotNullOrEmpty(desiredName, nameof(desiredName));
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+ EnsureExists();
+
+ var nameToUse = desiredName;
+ var newPath = System.IO.Path.Combine(Path, nameToUse);
+ if (File.Exists(newPath))
+ {
+ if (option == CreationCollisionOption.GenerateUniqueName)
+ {
+ var desiredRoot = System.IO.Path.GetFileNameWithoutExtension(desiredName);
+ var desiredExtension = System.IO.Path.GetExtension(desiredName);
+ for (var num = 2; File.Exists(newPath); num++)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ nameToUse = $"{desiredRoot} ({num}){desiredExtension}";
+ newPath = System.IO.Path.Combine(Path, nameToUse);
+ }
+ InternalCreateFile(newPath);
+ }
+ else if (option == CreationCollisionOption.ReplaceExisting)
+ {
+ File.Delete(newPath);
+ InternalCreateFile(newPath);
+ }
+ else if (option == CreationCollisionOption.FailIfExists)
+ throw new IOException($"File already exists: {newPath}");
+ else if (option == CreationCollisionOption.OpenIfExists)
+ {
+ // No operation.
+ }
+ else
+ throw new ArgumentException($"Unrecognized CreationCollisionOption: {option}");
+ }
+ else
+ {
+ // Create file.
+ InternalCreateFile(newPath);
+ }
+
+ return new NETCOREFileImplementation(newPath);
+ }
+ void InternalCreateFile(string path)
+ {
+ using (var stream = File.Create(path)) { }
+ }
+
+ ///
+ public IFile GetFile(string name)
+ {
+ var path = System.IO.Path.Combine(Path, name);
+ if (!File.Exists(path))
+ throw new FileNotFoundException($"File does not exist: {path}");
+ return new NETCOREFileImplementation(path);
+ }
+ ///
+ public async Task GetFileAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ var path = System.IO.Path.Combine(Path, name);
+ if (!File.Exists(path))
+ throw new FileNotFoundException($"File does not exist: {path}");
+ return new NETCOREFileImplementation(path);
+ }
+
+ ///
+ public IList GetFiles(string searchPattern = "*", FolderSearchOption searchOption = FolderSearchOption.TopFolderOnly)
+ {
+ EnsureExists();
+ return Directory.GetFiles(Path, searchPattern, (SearchOption) searchOption).Select(f => new NETCOREFileImplementation(f)).ToList().AsReadOnly();
+ }
+ ///
+ public async Task> GetFilesAsync(string searchPattern = "*", FolderSearchOption searchOption = FolderSearchOption.TopFolderOnly, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ EnsureExists();
+ return Directory.GetFiles(Path, searchPattern, (SearchOption) searchOption).Select(f => new NETCOREFileImplementation(f)).ToList().AsReadOnly();
+ }
+
+ ///
+ public IFolder CreateFolder(string desiredName, CreationCollisionOption option)
+ {
+ Requires.NotNullOrEmpty(desiredName, nameof(desiredName));
+
+ EnsureExists();
+ var nameToUse = desiredName;
+ var newPath = System.IO.Path.Combine(Path, nameToUse);
+ if (Directory.Exists(newPath))
+ {
+ if (option == CreationCollisionOption.GenerateUniqueName)
+ {
+ for (var num = 2; Directory.Exists(newPath); num++)
+ {
+ nameToUse = $"{desiredName} ({num})";
+ newPath = System.IO.Path.Combine(Path, nameToUse);
+ }
+ Directory.CreateDirectory(newPath);
+ }
+ else if (option == CreationCollisionOption.ReplaceExisting)
+ {
+ Directory.Delete(newPath, true);
+ Directory.CreateDirectory(newPath);
+ }
+ else if (option == CreationCollisionOption.FailIfExists)
+ throw new IOException($"Directory already exists: {newPath}");
+
+ else if (option == CreationCollisionOption.OpenIfExists)
+ {
+ // No operation.
+ }
+ else
+ throw new ArgumentException($"Unrecognized CreationCollisionOption: {option}");
+ }
+ else
+ Directory.CreateDirectory(newPath);
+
+ return new NETCOREFolderImplementation(newPath, true);
+ }
+ ///
+ public async Task CreateFolderAsync(string desiredName, CreationCollisionOption option, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ Requires.NotNullOrEmpty(desiredName, nameof(desiredName));
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ EnsureExists();
+ var nameToUse = desiredName;
+ var newPath = System.IO.Path.Combine(Path, nameToUse);
+ if (Directory.Exists(newPath))
+ {
+ if (option == CreationCollisionOption.GenerateUniqueName)
+ {
+ for (var num = 2; Directory.Exists(newPath); num++)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ nameToUse = $"{desiredName} ({num})";
+ newPath = System.IO.Path.Combine(Path, nameToUse);
+ }
+ Directory.CreateDirectory(newPath);
+ }
+ else if (option == CreationCollisionOption.ReplaceExisting)
+ {
+ Directory.Delete(newPath, true);
+ Directory.CreateDirectory(newPath);
+ }
+ else if (option == CreationCollisionOption.FailIfExists)
+ throw new IOException($"Directory already exists: {newPath}");
+
+ else if (option == CreationCollisionOption.OpenIfExists)
+ {
+ // No operation.
+ }
+ else
+ throw new ArgumentException($"Unrecognized CreationCollisionOption: {option}");
+ }
+ else
+ Directory.CreateDirectory(newPath);
+
+ return new NETCOREFolderImplementation(newPath, true);
+ }
+
+ ///
+ public IFolder GetFolder(string name)
+ {
+ Requires.NotNullOrEmpty(name, nameof(name));
+
+ var path = System.IO.Path.Combine(Path, name);
+ if (!Directory.Exists(path))
+ throw new DirectoryNotFoundException($"Directory does not exist: {path}");
+ return new NETCOREFolderImplementation(path, true);
+ }
+ ///
+ public async Task GetFolderAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ Requires.NotNullOrEmpty(name, nameof(name));
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ var path = System.IO.Path.Combine(Path, name);
+ if (!Directory.Exists(path))
+ throw new DirectoryNotFoundException($"Directory does not exist: {path}");
+ return new NETCOREFolderImplementation(path, true);
+ }
+
+ ///
+ public IList GetFolders()
+ {
+ EnsureExists();
+ return Directory.GetDirectories(Path).Select(d => new NETCOREFolderImplementation(d, true)).ToList().AsReadOnly();
+ }
+ ///
+ public async Task> GetFoldersAsync(CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ EnsureExists();
+ return Directory.GetDirectories(Path).Select(d => new NETCOREFolderImplementation(d, true)).ToList().AsReadOnly();
+ }
+
+ ///
+ public ExistenceCheckResult CheckExists(string name)
+ {
+ Requires.NotNullOrEmpty(name, "name");
+
+ var checkPath = System.IO.Path.Combine(Path, name);
+ if (File.Exists(checkPath))
+ return ExistenceCheckResult.FileExists;
+ else if (Directory.Exists(checkPath))
+ return ExistenceCheckResult.FolderExists;
+ else
+ return ExistenceCheckResult.NotFound;
+ }
+ ///
+ public async Task CheckExistsAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ Requires.NotNullOrEmpty(name, "name");
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ var checkPath = System.IO.Path.Combine(Path, name);
+ if (File.Exists(checkPath))
+ return ExistenceCheckResult.FileExists;
+ else if (Directory.Exists(checkPath))
+ return ExistenceCheckResult.FolderExists;
+ else
+ return ExistenceCheckResult.NotFound;
+ }
+
+ ///
+ public void Delete()
+ {
+ if (!_canDelete)
+ throw new IOException("Cannot delete root storage folder.");
+
+ EnsureExists();
+ Directory.Delete(Path, true);
+ }
+ ///
+ public async Task DeleteAsync(CancellationToken cancellationToken)
+ {
+ if (!_canDelete)
+ throw new IOException("Cannot delete root storage folder.");
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ EnsureExists();
+ Directory.Delete(Path, true);
+ }
+
+ ///
+ public IFolder Move(IFolder folder, NameCollisionOption option = NameCollisionOption.ReplaceExisting)
+ {
+ Requires.NotNull(folder, nameof(folder));
+
+ EnsureExists();
+
+ var files = GetFiles();
+ foreach (var file in files)
+ file.Move(System.IO.Path.Combine(folder.Path, file.Name), option);
+
+ var folders = GetFolders();
+ foreach (var nFolder in folders)
+ nFolder.Move(folder.CreateFolder(nFolder.Name, CreationCollisionOption.OpenIfExists), option);
+
+ Delete();
+ return folder;
+ }
+ ///
+ public async Task MoveAsync(IFolder folder, NameCollisionOption option = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ Requires.NotNull(folder, nameof(folder));
+
+ await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
+
+ EnsureExists();
+
+ var files = await GetFilesAsync(cancellationToken: cancellationToken);
+ foreach (var file in files)
+ await file.MoveAsync(System.IO.Path.Combine(folder.Path, file.Name), option, cancellationToken);
+
+ var folders = await GetFoldersAsync(cancellationToken);
+ foreach (var nFolder in folders)
+ await nFolder.MoveAsync(await folder.CreateFolderAsync(nFolder.Name, CreationCollisionOption.OpenIfExists, cancellationToken), option, cancellationToken);
+
+ await DeleteAsync(cancellationToken);
+ return folder;
+ }
+
+ void EnsureExists()
+ {
+ if (!Directory.Exists(Path))
+ throw new DirectoryNotFoundException("Directory does not exist: " + Path);
+ }
+ }
+}
diff --git a/src/PCLExt.FileStorage.Core/PCLExt.FileStorage.Core.csproj b/src/PCLExt.FileStorage.Core/PCLExt.FileStorage.Core.csproj
new file mode 100644
index 0000000..9733577
--- /dev/null
+++ b/src/PCLExt.FileStorage.Core/PCLExt.FileStorage.Core.csproj
@@ -0,0 +1,51 @@
+
+
+
+ netstandard1.3
+ PCLExt.FileStorage
+ False
+ false
+ PCLExt.FileStorage
+
+
+
+ TRACE;CORE
+ bin\Release\netstandard1.3\PCLExt.FileStorage.xml
+
+
+
+ TRACE;DEBUG;CORE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Core/Properties/AssemblyInfo.cs b/src/PCLExt.FileStorage.Core/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ae5785a
--- /dev/null
+++ b/src/PCLExt.FileStorage.Core/Properties/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+using System.Reflection;
+
+[assembly: AssemblyTitle("PCLExt.FileStorage.Core")]
+[assembly: AssemblyDescription("")]
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Desktop/DesktopFileSystem.cs b/src/PCLExt.FileStorage.Desktop/DesktopFileSystem.cs
deleted file mode 100644
index c4e11e6..0000000
--- a/src/PCLExt.FileStorage.Desktop/DesktopFileSystem.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-//-----------------------------------------------------------------------
-//
-// Copyright (c) Daniel Plaisted. All rights reserved.
-//
-// This file is a derivation of:
-// https://github.com/dsplaisted/PCLStorage
-// Which is released under the MS-PL license.
-//-----------------------------------------------------------------------
-
-namespace PCLExt.FileStorage
-{
- ///
- /// Implementation of over classic .NET file I/O APIs.
- ///
- public class DesktopFileSystem : IFileSystem
- {
-#if MAC
- [System.Runtime.InteropServices.DllImport(ObjCRuntime.Constants.FoundationLibrary)]
- static extern System.IntPtr NSHomeDirectory(); // Under the sandbox, need to read the HomeDirectory
-
- static string MacHomeDirectory => ((Foundation.NSString)ObjCRuntime.Runtime.GetNSObject(NSHomeDirectory())).ToString();
-#endif
-
- ///
- public IFolder BaseStorage
- {
- get
- {
-#if ANDROID || __IOS__
- var storage = "";
- return null;
-#elif DESKTOP || MAC
- var storage = System.AppDomain.CurrentDomain.BaseDirectory;
-#endif
- return new FileSystemFolder(storage);
- }
- }
-
- ///
- public IFolder LocalStorage
- {
- get
- {
-#if ANDROID
- var storage = Android.App.Application.Context.GetExternalFilesDir(null)?.ParentFile?.AbsolutePath;
- if(string.IsNullOrEmpty(storage))
- return null;
-#elif __IOS__
- var documents = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
- var storage = System.IO.Path.Combine(documents, "..", "Library");
-#elif MAC
- // (non-sandboxed) /Users/foo/Library/Application Support/ProcessName/
- // (sandboxed) /Users/foo/Library/Containers//Data/Library/Application Support/ProcessName/
- var name = System.IO.Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().ProcessName);
- var storage = System.IO.Path.Combine(MacHomeDirectory, "Library", "Application Support");
- if(!string.IsNullOrEmpty(name))
- {
- storage = System.IO.Path.Combine(storage, name);
- if(!System.IO.Directory.Exists(storage)) // Ensure it exists to stope FileSystemFolder from throwing exception.
- System.IO.Directory.CreateDirectory(storage);
- }
-#elif DESKTOP
- var storage = System.Windows.Forms.Application.LocalUserAppDataPath; // SpecialFolder.LocalApplicationData is not app-specific, so use the Windows Forms API to get the app data path.
-#endif
- return new FileSystemFolder(storage);
- }
- }
-
- ///
- public IFolder RoamingStorage
- {
- get
- {
-#if ANDROID
- var storage = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
-
-#elif __IOS__ || MAC
- var storage = "";
- return null;
-#elif DESKTOP
- var storage = System.Windows.Forms.Application.UserAppDataPath; // SpecialFolder.ApplicationData is not app-specific, so use the Windows Forms API to get the app data path.
-#endif
- return new FileSystemFolder(storage);
- }
- }
-
- ///
- public IFolder SpecialStorage
- {
- get
- {
-#if DESKTOP || MAC
- return BaseStorage;
-
-#elif ANDROID || __IOS__
- return LocalStorage;
-#endif
-
- return null;
- }
- }
- }
-}
diff --git a/src/PCLExt.FileStorage.Desktop/FileSystemFile.cs b/src/PCLExt.FileStorage.Desktop/NET4FileImplementation.cs
similarity index 98%
rename from src/PCLExt.FileStorage.Desktop/FileSystemFile.cs
rename to src/PCLExt.FileStorage.Desktop/NET4FileImplementation.cs
index 226ff50..0dd9b01 100644
--- a/src/PCLExt.FileStorage.Desktop/FileSystemFile.cs
+++ b/src/PCLExt.FileStorage.Desktop/NET4FileImplementation.cs
@@ -12,6 +12,7 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using PCLExt.FileStorage.Extensions;
namespace PCLExt.FileStorage
{
@@ -19,7 +20,7 @@ namespace PCLExt.FileStorage
/// Represents a file in the .
///
[DebuggerDisplay("Name = {" + nameof(Name) + "}")]
- public class FileSystemFile : IFile
+ internal class NET4FileImplementation : IFile
{
///
public string Name { get; private set; }
@@ -30,7 +31,7 @@ public class FileSystemFile : IFile
/// Creates a new corresponding to the specified path.
///
/// The file path
- public FileSystemFile(string path)
+ public NET4FileImplementation(string path)
{
Name = System.IO.Path.GetFileName(path);
Path = path;
diff --git a/src/PCLExt.FileStorage.Desktop/FileSystemFolder.cs b/src/PCLExt.FileStorage.Desktop/NET4FolderImplementation.cs
similarity index 93%
rename from src/PCLExt.FileStorage.Desktop/FileSystemFolder.cs
rename to src/PCLExt.FileStorage.Desktop/NET4FolderImplementation.cs
index ae57628..d9da568 100644
--- a/src/PCLExt.FileStorage.Desktop/FileSystemFolder.cs
+++ b/src/PCLExt.FileStorage.Desktop/NET4FolderImplementation.cs
@@ -14,6 +14,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using PCLExt.FileStorage.Extensions;
namespace PCLExt.FileStorage
{
@@ -21,7 +22,7 @@ namespace PCLExt.FileStorage
/// Represents a folder in the .
///
[DebuggerDisplay("Name = {" + nameof(Name) + "}")]
- public class FileSystemFolder : IFolder
+ internal class NET4FolderImplementation : IFolder
{
private readonly bool _canDelete;
@@ -35,7 +36,7 @@ public class FileSystemFolder : IFolder
///
/// The folder path.
/// Specifies whether the folder can be deleted (via ).
- public FileSystemFolder(string path, bool canDelete = false) { Name = System.IO.Path.GetFileName(path); Path = path; _canDelete = canDelete; }
+ public NET4FolderImplementation(string path, bool canDelete = false) { Name = System.IO.Path.GetFileName(path); Path = path; _canDelete = canDelete; }
///
public IFile CreateFile(string desiredName, CreationCollisionOption option)
@@ -79,7 +80,7 @@ public IFile CreateFile(string desiredName, CreationCollisionOption option)
InternalCreateFile(newPath);
}
- return new FileSystemFile(newPath);
+ return new NET4FileImplementation(newPath);
}
///
public async Task CreateFileAsync(string desiredName, CreationCollisionOption option, CancellationToken cancellationToken = default(CancellationToken))
@@ -125,7 +126,7 @@ public IFile CreateFile(string desiredName, CreationCollisionOption option)
InternalCreateFile(newPath);
}
- return new FileSystemFile(newPath);
+ return new NET4FileImplementation(newPath);
}
void InternalCreateFile(string path)
{
@@ -138,7 +139,7 @@ public IFile GetFile(string name)
var path = System.IO.Path.Combine(Path, name);
if (!File.Exists(path))
throw new FileNotFoundException($"File does not exist: {path}");
- return new FileSystemFile(path);
+ return new NET4FileImplementation(path);
}
///
public async Task GetFileAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
@@ -148,14 +149,14 @@ public IFile GetFile(string name)
var path = System.IO.Path.Combine(Path, name);
if (!File.Exists(path))
throw new FileNotFoundException($"File does not exist: {path}");
- return new FileSystemFile(path);
+ return new NET4FileImplementation(path);
}
///
public IList GetFiles(string searchPattern = "*", FolderSearchOption searchOption = FolderSearchOption.TopFolderOnly)
{
EnsureExists();
- return Directory.GetFiles(Path, searchPattern, (SearchOption) searchOption).Select(f => new FileSystemFile(f)).ToList().AsReadOnly();
+ return Directory.GetFiles(Path, searchPattern, (SearchOption) searchOption).Select(f => new NET4FileImplementation(f)).ToList().AsReadOnly();
}
///
public async Task> GetFilesAsync(string searchPattern = "*", FolderSearchOption searchOption = FolderSearchOption.TopFolderOnly, CancellationToken cancellationToken = default(CancellationToken))
@@ -163,7 +164,7 @@ public IList GetFiles(string searchPattern = "*", FolderSearchOption sear
await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
EnsureExists();
- return Directory.GetFiles(Path, searchPattern, (SearchOption) searchOption).Select(f => new FileSystemFile(f)).ToList().AsReadOnly();
+ return Directory.GetFiles(Path, searchPattern, (SearchOption) searchOption).Select(f => new NET4FileImplementation(f)).ToList().AsReadOnly();
}
///
@@ -203,7 +204,7 @@ public IFolder CreateFolder(string desiredName, CreationCollisionOption option)
else
Directory.CreateDirectory(newPath);
- return new FileSystemFolder(newPath, true);
+ return new NET4FolderImplementation(newPath, true);
}
///
public async Task CreateFolderAsync(string desiredName, CreationCollisionOption option, CancellationToken cancellationToken = default(CancellationToken))
@@ -245,7 +246,7 @@ public IFolder CreateFolder(string desiredName, CreationCollisionOption option)
else
Directory.CreateDirectory(newPath);
- return new FileSystemFolder(newPath, true);
+ return new NET4FolderImplementation(newPath, true);
}
///
@@ -256,7 +257,7 @@ public IFolder GetFolder(string name)
var path = System.IO.Path.Combine(Path, name);
if (!Directory.Exists(path))
throw new DirectoryNotFoundException($"Directory does not exist: {path}");
- return new FileSystemFolder(path, true);
+ return new NET4FolderImplementation(path, true);
}
///
public async Task GetFolderAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
@@ -268,14 +269,14 @@ public IFolder GetFolder(string name)
var path = System.IO.Path.Combine(Path, name);
if (!Directory.Exists(path))
throw new DirectoryNotFoundException($"Directory does not exist: {path}");
- return new FileSystemFolder(path, true);
+ return new NET4FolderImplementation(path, true);
}
///
public IList GetFolders()
{
EnsureExists();
- return Directory.GetDirectories(Path).Select(d => new FileSystemFolder(d, true)).ToList().AsReadOnly();
+ return Directory.GetDirectories(Path).Select(d => new NET4FolderImplementation(d, true)).ToList().AsReadOnly();
}
///
public async Task> GetFoldersAsync(CancellationToken cancellationToken = default(CancellationToken))
@@ -283,7 +284,7 @@ public IList GetFolders()
await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
EnsureExists();
- return Directory.GetDirectories(Path).Select(d => new FileSystemFolder(d, true)).ToList().AsReadOnly();
+ return Directory.GetDirectories(Path).Select(d => new NET4FolderImplementation(d, true)).ToList().AsReadOnly();
}
///
diff --git a/src/PCLExt.FileStorage.Desktop/PCLExt.FileStorage.Desktop.csproj b/src/PCLExt.FileStorage.Desktop/PCLExt.FileStorage.Desktop.csproj
index 16d7674..ee5bdd9 100644
--- a/src/PCLExt.FileStorage.Desktop/PCLExt.FileStorage.Desktop.csproj
+++ b/src/PCLExt.FileStorage.Desktop/PCLExt.FileStorage.Desktop.csproj
@@ -34,42 +34,80 @@
-
-
-
-
-
-
-
+
Properties\CommonAssemblyInfo.cs
-
- AwaitExtensions.cs
+
+ BaseFile.cs
-
- FileSystem.cs
+
+ BaseFolder.cs
-
- PortablePath.cs
+
+ CreationCollisionOption.cs
-
- Requires.cs
+
+ ExistenceCheckResult.cs
-
- BaseFolder.cs
+
+ FolderSearchOption.cs
-
- BaseFile.cs
+
+ IFile.cs
+
+
+ IFolder.cs
+
+
+ NameCollisionOption.cs
+
+
+ Exceptions\DirectoryNotFoundException.cs
+
+
+ Exceptions\ExceptionsHelper.cs
+
+
+ Exceptions\FileNotFoundException.cs
+
+
+ Extensions\AwaitExtensions.cs
+
+
+ Extensions\FileExtensions.cs
+
+
+ Extensions\FolderExtensions.cs
+
+
+ Files\FileFromPath.cs
+
+
+ Folders\ApplicationFolder.cs
+
+
+ Folders\FolderFromPath.cs
+
+
+ Folders\LocalFolder.cs
+
+
+ Folders\RoamingFolder.cs
+
+
+ PortablePath.cs
+
+
+ Requires.cs
-
-
-
+
+
-
+
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}
PCLExt.FileStorage.Abstractions
diff --git a/src/PCLExt.FileStorage.Mac/PCLExt.FileStorage.Mac.csproj b/src/PCLExt.FileStorage.Mac/PCLExt.FileStorage.Mac.csproj
index 6645ef6..b718c4d 100644
--- a/src/PCLExt.FileStorage.Mac/PCLExt.FileStorage.Mac.csproj
+++ b/src/PCLExt.FileStorage.Mac/PCLExt.FileStorage.Mac.csproj
@@ -51,34 +51,76 @@
-
- AwaitExtensions.cs
+
+ BaseFile.cs
-
- FileSystem.cs
+
+ BaseFolder.cs
-
- PortablePath.cs
+
+ CreationCollisionOption.cs
-
- Requires.cs
+
+ ExistenceCheckResult.cs
-
- BaseFolder.cs
+
+ FolderSearchOption.cs
-
- BaseFile.cs
+
+ IFile.cs
+
+
+ IFolder.cs
+
+
+ NameCollisionOption.cs
+
+
+ Exceptions\DirectoryNotFoundException.cs
+
+
+ Exceptions\ExceptionsHelper.cs
+
+
+ Exceptions\FileNotFoundException.cs
-
- DesktopFileSystem.cs
+
+ Extensions\AwaitExtensions.cs
-
- FileSystemFolder.cs
+
+ Extensions\FileExtensions.cs
-
- FileSystemFile.cs
+
+ Extensions\FolderExtensions.cs
+
+
+ Files\FileFromPath.cs
+
+
+ Folders\ApplicationFolder.cs
+
+
+ Folders\FolderFromPath.cs
+
+
+ Folders\LocalFolder.cs
+
+
+ Folders\RoamingFolder.cs
+
+
+ NET4FileImplementation.cs
+
+
+ NET4FolderImplementation.cs
+
+
+ PortablePath.cs
+
+
+ Requires.cs
-
+
Properties\CommonAssemblyInfo.cs
@@ -86,7 +128,7 @@
-
+
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}
PCLExt.FileStorage.Abstractions
diff --git a/src/PCLExt.FileStorage/BaseFile.cs b/src/PCLExt.FileStorage.Portable.Abstractions/BaseFile.cs
similarity index 93%
rename from src/PCLExt.FileStorage/BaseFile.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/BaseFile.cs
index 783e0a1..3384a8e 100644
--- a/src/PCLExt.FileStorage/BaseFile.cs
+++ b/src/PCLExt.FileStorage.Portable.Abstractions/BaseFile.cs
@@ -21,11 +21,6 @@ public abstract class BaseFile : IFile
///
///
public BaseFile(IFile file) { _file = file; }
- ///
- ///
- ///
- ///
- public BaseFile(string path) : this(FileSystem.GetFileFromPath(path)) { }
///
public Stream Open(FileAccess fileAccess) => _file.Open(fileAccess);
@@ -52,4 +47,4 @@ public BaseFile(string path) : this(FileSystem.GetFileFromPath(path)) { }
///
public Task CopyAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) => _file.CopyAsync(newPath, collisionOption, cancellationToken);
}
-}
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage/BaseFolder.cs b/src/PCLExt.FileStorage.Portable.Abstractions/BaseFolder.cs
similarity index 95%
rename from src/PCLExt.FileStorage/BaseFolder.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/BaseFolder.cs
index 36b7c78..a3f16b6 100644
--- a/src/PCLExt.FileStorage/BaseFolder.cs
+++ b/src/PCLExt.FileStorage.Portable.Abstractions/BaseFolder.cs
@@ -21,11 +21,6 @@ public abstract class BaseFolder : IFolder
///
///
protected BaseFolder(IFolder folder) { _folder = folder; }
- ///
- ///
- ///
- ///
- protected BaseFolder(string path) : this(FileSystem.GetFolderFromPath(path)) { }
///
public IFile GetFile(string name) => _folder.GetFile(name);
@@ -72,4 +67,4 @@ protected BaseFolder(string path) : this(FileSystem.GetFolderFromPath(path)) { }
///
public Task MoveAsync(IFolder folder, NameCollisionOption option = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = new CancellationToken()) => _folder.MoveAsync(folder, option, cancellationToken);
}
-}
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Portable.Abstractions/CreationCollisionOption.cs b/src/PCLExt.FileStorage.Portable.Abstractions/CreationCollisionOption.cs
new file mode 100644
index 0000000..5a57f99
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable.Abstractions/CreationCollisionOption.cs
@@ -0,0 +1,34 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Daniel Plaisted. All rights reserved.
+//
+// This file is a derivation of:
+// https://github.com/dsplaisted/PCLStorage
+// Which is released under the MS-PL license.
+//-----------------------------------------------------------------------
+
+namespace PCLExt.FileStorage
+{
+ ///
+ /// Specifies what should happen when trying to create a file or folder that already exists.
+ ///
+ public enum CreationCollisionOption
+ {
+ ///
+ /// Creates a new file with a unique name of the form "name (2).txt"
+ ///
+ GenerateUniqueName = 0,
+ ///
+ /// Replaces any existing file with a new (empty) one
+ ///
+ ReplaceExisting = 1,
+ ///
+ /// Throws an exception if the file exists
+ ///
+ FailIfExists = 2,
+ ///
+ /// Opens the existing file, if any
+ ///
+ OpenIfExists = 3,
+ }
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Abstractions/ExistenceCheckResult.cs b/src/PCLExt.FileStorage.Portable.Abstractions/ExistenceCheckResult.cs
similarity index 99%
rename from src/PCLExt.FileStorage.Abstractions/ExistenceCheckResult.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/ExistenceCheckResult.cs
index 61c3430..9dbca4e 100644
--- a/src/PCLExt.FileStorage.Abstractions/ExistenceCheckResult.cs
+++ b/src/PCLExt.FileStorage.Portable.Abstractions/ExistenceCheckResult.cs
@@ -29,4 +29,4 @@ public enum ExistenceCheckResult
///
FolderExists,
}
-}
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Abstractions/FolderSearchOption.cs b/src/PCLExt.FileStorage.Portable.Abstractions/FolderSearchOption.cs
similarity index 98%
rename from src/PCLExt.FileStorage.Abstractions/FolderSearchOption.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/FolderSearchOption.cs
index 6c40b05..485fce8 100644
--- a/src/PCLExt.FileStorage.Abstractions/FolderSearchOption.cs
+++ b/src/PCLExt.FileStorage.Portable.Abstractions/FolderSearchOption.cs
@@ -5,4 +5,4 @@ public enum FolderSearchOption
TopFolderOnly,
AllFolders,
}
-}
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Abstractions/IFile.cs b/src/PCLExt.FileStorage.Portable.Abstractions/IFile.cs
similarity index 100%
rename from src/PCLExt.FileStorage.Abstractions/IFile.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/IFile.cs
diff --git a/src/PCLExt.FileStorage.Abstractions/IFolder.cs b/src/PCLExt.FileStorage.Portable.Abstractions/IFolder.cs
similarity index 92%
rename from src/PCLExt.FileStorage.Abstractions/IFolder.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/IFolder.cs
index 531e74e..272ccca 100644
--- a/src/PCLExt.FileStorage.Abstractions/IFolder.cs
+++ b/src/PCLExt.FileStorage.Portable.Abstractions/IFolder.cs
@@ -13,29 +13,6 @@
namespace PCLExt.FileStorage
{
- ///
- /// Specifies what should happen when trying to create a file or folder that already exists.
- ///
- public enum CreationCollisionOption
- {
- ///
- /// Creates a new file with a unique name of the form "name (2).txt"
- ///
- GenerateUniqueName = 0,
- ///
- /// Replaces any existing file with a new (empty) one
- ///
- ReplaceExisting = 1,
- ///
- /// Throws an exception if the file exists
- ///
- FailIfExists = 2,
- ///
- /// Opens the existing file, if any
- ///
- OpenIfExists = 3,
- }
-
///
/// Represents a file system folder
///
diff --git a/src/PCLExt.FileStorage.Abstractions/NameCollisionOption.cs b/src/PCLExt.FileStorage.Portable.Abstractions/NameCollisionOption.cs
similarity index 100%
rename from src/PCLExt.FileStorage.Abstractions/NameCollisionOption.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/NameCollisionOption.cs
diff --git a/src/PCLExt.FileStorage.Abstractions/PCLExt.FileStorage.Abstractions.csproj b/src/PCLExt.FileStorage.Portable.Abstractions/PCLExt.FileStorage.Portable.Abstractions.csproj
similarity index 92%
rename from src/PCLExt.FileStorage.Abstractions/PCLExt.FileStorage.Abstractions.csproj
rename to src/PCLExt.FileStorage.Portable.Abstractions/PCLExt.FileStorage.Portable.Abstractions.csproj
index 89a7188..a4f5799 100644
--- a/src/PCLExt.FileStorage.Abstractions/PCLExt.FileStorage.Abstractions.csproj
+++ b/src/PCLExt.FileStorage.Portable.Abstractions/PCLExt.FileStorage.Portable.Abstractions.csproj
@@ -34,14 +34,15 @@
bin\Release\PCLExt.FileStorage.Abstractions.xml
-
+
Properties\CommonAssemblyInfo.cs
+
+
+
-
-
diff --git a/src/PCLExt.FileStorage.Abstractions/Properties/AssemblyInfo.cs b/src/PCLExt.FileStorage.Portable.Abstractions/Properties/AssemblyInfo.cs
similarity index 100%
rename from src/PCLExt.FileStorage.Abstractions/Properties/AssemblyInfo.cs
rename to src/PCLExt.FileStorage.Portable.Abstractions/Properties/AssemblyInfo.cs
diff --git a/src/PCLExt.FileStorage/Exceptions.cs b/src/PCLExt.FileStorage.Portable/Exceptions/DirectoryNotFoundException.cs
similarity index 57%
rename from src/PCLExt.FileStorage/Exceptions.cs
rename to src/PCLExt.FileStorage.Portable/Exceptions/DirectoryNotFoundException.cs
index 9b4b44f..70ddc60 100644
--- a/src/PCLExt.FileStorage/Exceptions.cs
+++ b/src/PCLExt.FileStorage.Portable/Exceptions/DirectoryNotFoundException.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------
+//-----------------------------------------------------------------------
//
// Copyright (c) Daniel Plaisted. All rights reserved.
//
@@ -8,30 +8,14 @@
//-----------------------------------------------------------------------
using System;
-using System.IO;
-namespace PCLExt.FileStorage
+namespace PCLExt.FileStorage.Exceptions
{
- ///
- public class FileNotFoundException
-#if PORTABLE
- : IOException
-#else
- : System.IO.FileNotFoundException
-#endif
- {
- ///
- public FileNotFoundException(string message) : base(message) { }
-
- ///
- public FileNotFoundException(string message, Exception innerException) : base(message, innerException) { }
- }
-
///
public class DirectoryNotFoundException
#if PORTABLE
- : IOException
-#elif NETFX_CORE
+ : System.IO.IOException
+#elif CORE
: System.IO.FileNotFoundException
#else
: System.IO.DirectoryNotFoundException
@@ -43,4 +27,4 @@ public DirectoryNotFoundException(string message) : base(message) { }
///
public DirectoryNotFoundException(string message, Exception innerException) : base(message, innerException) { }
}
-}
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Portable/Exceptions/ExceptionsHelper.cs b/src/PCLExt.FileStorage.Portable/Exceptions/ExceptionsHelper.cs
new file mode 100644
index 0000000..a0bb0dd
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Exceptions/ExceptionsHelper.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace PCLExt.FileStorage.Exceptions
+{
+ internal static class ExceptionsHelper
+ {
+ internal static Exception NotImplementedInReferenceAssembly() =>
+ new NotImplementedException(@"This functionality is not implemented in the portable version of this assembly.
+You should reference the PCLExt.FileStorage NuGet package from your main application project in order to reference the platform-specific implementation.");
+
+ internal static Exception NotImplementedInNetStandard() =>
+ new NotImplementedException(@"This functionality is not implemented in the current version of this .NET Standard.
+You should wait for .NET Standard 2.0.");
+ }
+}
diff --git a/src/PCLExt.FileStorage.Portable/Exceptions/FileNotFoundException.cs b/src/PCLExt.FileStorage.Portable/Exceptions/FileNotFoundException.cs
new file mode 100644
index 0000000..e6e6293
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Exceptions/FileNotFoundException.cs
@@ -0,0 +1,28 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Daniel Plaisted. All rights reserved.
+//
+// This file is a derivation of:
+// https://github.com/dsplaisted/PCLStorage
+// Which is released under the MS-PL license.
+//-----------------------------------------------------------------------
+
+using System;
+
+namespace PCLExt.FileStorage.Exceptions
+{
+ ///
+ public class FileNotFoundException
+#if PORTABLE
+ : System.IO.IOException
+#else
+ : System.IO.FileNotFoundException
+#endif
+ {
+ ///
+ public FileNotFoundException(string message) : base(message) { }
+
+ ///
+ public FileNotFoundException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage/AwaitExtensions.cs b/src/PCLExt.FileStorage.Portable/Extensions/AwaitExtensions.cs
similarity index 98%
rename from src/PCLExt.FileStorage/AwaitExtensions.cs
rename to src/PCLExt.FileStorage.Portable/Extensions/AwaitExtensions.cs
index 66ccfb6..e369d64 100644
--- a/src/PCLExt.FileStorage/AwaitExtensions.cs
+++ b/src/PCLExt.FileStorage.Portable/Extensions/AwaitExtensions.cs
@@ -12,7 +12,7 @@
using System.Threading;
using System.Threading.Tasks;
-namespace PCLExt.FileStorage
+namespace PCLExt.FileStorage.Extensions
{
///
/// Extensions for use internally by PCLStorage for awaiting.
diff --git a/src/PCLExt.FileStorage.Abstractions/FileExtensions.cs b/src/PCLExt.FileStorage.Portable/Extensions/FileExtensions.cs
similarity index 99%
rename from src/PCLExt.FileStorage.Abstractions/FileExtensions.cs
rename to src/PCLExt.FileStorage.Portable/Extensions/FileExtensions.cs
index a5ba658..ed36e57 100644
--- a/src/PCLExt.FileStorage.Abstractions/FileExtensions.cs
+++ b/src/PCLExt.FileStorage.Portable/Extensions/FileExtensions.cs
@@ -11,7 +11,7 @@
using System.IO;
using System.Threading.Tasks;
-namespace PCLExt.FileStorage
+namespace PCLExt.FileStorage.Extensions
{
///
/// Provides extension methods for the class
@@ -206,4 +206,4 @@ public static async Task AppendLinesAsync(this IFile file, IEnumerable l
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Portable/Extensions/FolderExtensions.cs b/src/PCLExt.FileStorage.Portable/Extensions/FolderExtensions.cs
new file mode 100644
index 0000000..e208a48
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Extensions/FolderExtensions.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Linq;
+
+namespace PCLExt.FileStorage.Extensions
+{
+ ///
+ /// Provides extension methods for and class
+ ///
+ public static class FolderExtensions
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IFolder GetFolderFromPath(this IFolder folder, string folderPath)
+ {
+ var folders = folderPath.Split(new[]
+ {
+#if DESKTOP || ANDROID || __IOS__ || MAC || PORTABLE
+ PortablePath.DirectorySeparatorChar
+#elif CORE
+ System.IO.Path.DirectorySeparatorChar
+#endif
+ }, StringSplitOptions.RemoveEmptyEntries);
+
+ return GetFolderFromPath(folder, folders);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IFolder GetFolderFromPath(this IFolder folder, params string[] folders)
+ {
+ if (folders != null)
+ foreach (var folderName in folders)
+ folder = folder.CreateFolder(folderName, CreationCollisionOption.OpenIfExists);
+
+ return folder;
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IFile GetFileFromPath(this IFolder folder, string filePath)
+ {
+ var foldersWithFile = filePath.Split(new[]
+ {
+#if DESKTOP || ANDROID || __IOS__ || MAC || PORTABLE
+ PortablePath.DirectorySeparatorChar
+#elif CORE
+ System.IO.Path.DirectorySeparatorChar
+#endif
+ }, StringSplitOptions.RemoveEmptyEntries);
+
+ return GetFileFromPath(folder, foldersWithFile);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IFile GetFileFromPath(this IFolder folder, params string[] foldersWithFile)
+ {
+ var fileName = foldersWithFile.Last();
+ var folders = foldersWithFile.Length > 1 ? foldersWithFile.Take(foldersWithFile.Length - 1).ToArray() : null;
+
+ if (folders != null)
+ foreach (var folderName in folders)
+ folder = folder.CreateFolder(folderName, CreationCollisionOption.OpenIfExists);
+
+ return folder.CreateFile(fileName, CreationCollisionOption.OpenIfExists);
+ }
+ }
+}
diff --git a/src/PCLExt.FileStorage.Portable/Files/FileFromPath.cs b/src/PCLExt.FileStorage.Portable/Files/FileFromPath.cs
new file mode 100644
index 0000000..e2de2b5
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Files/FileFromPath.cs
@@ -0,0 +1,23 @@
+namespace PCLExt.FileStorage.Files
+{
+ public class FileFromPath : BaseFile
+ {
+ ///
+ ///
+ ///
+ ///
+ public FileFromPath(string path) : base(GetFileFromPath(path)) { }
+ private static IFile GetFileFromPath(string path)
+ {
+ Requires.NotNullOrEmpty(path, "path");
+
+#if DESKTOP || ANDROID || __IOS__ || MAC
+ return System.IO.File.Exists(path) ? new NET4FileImplementation(path) : null;
+#elif CORE
+ return System.IO.File.Exists(path) ? new NETCOREFileImplementation(path) : null;
+#endif
+
+ throw Exceptions.ExceptionsHelper.NotImplementedInReferenceAssembly();
+ }
+ }
+}
diff --git a/src/PCLExt.FileStorage.Portable/Folders/ApplicationFolder.cs b/src/PCLExt.FileStorage.Portable/Folders/ApplicationFolder.cs
new file mode 100644
index 0000000..070db09
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Folders/ApplicationFolder.cs
@@ -0,0 +1,29 @@
+namespace PCLExt.FileStorage.Folders
+{
+ ///
+ /// A folder representing storage which is where the app is running.
+ ///
+ public class ApplicationFolder : BaseFolder
+ {
+ ///
+ ///
+ ///
+#if DESKTOP || ANDROID || __IOS__ || MAC
+ public ApplicationFolder() : base(GetApplicationFolder()) { }
+ private static IFolder GetApplicationFolder()
+ {
+#if ANDROID || __IOS__
+ var storage = "";
+ return null;
+#elif DESKTOP || MAC
+ var storage = System.AppDomain.CurrentDomain.BaseDirectory;
+#endif
+ return new NET4FolderImplementation(storage);
+ }
+#elif CORE
+ public ApplicationFolder() : base(new NETCOREFolderImplementation(System.AppContext.BaseDirectory)) { }
+#else
+ public ApplicationFolder() : base(null) => throw Exceptions.ExceptionsHelper.NotImplementedInReferenceAssembly();
+#endif
+ }
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Portable/Folders/FolderFromPath.cs b/src/PCLExt.FileStorage.Portable/Folders/FolderFromPath.cs
new file mode 100644
index 0000000..e8e95b8
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Folders/FolderFromPath.cs
@@ -0,0 +1,24 @@
+namespace PCLExt.FileStorage.Folders
+{
+ public class FolderFromPath : BaseFolder
+ {
+ ///
+ ///
+ ///
+ ///
+ public FolderFromPath(string path) : base(GetFolderFromPath(path)) { }
+ private static IFolder GetFolderFromPath(string path)
+ {
+ Requires.NotNullOrEmpty(path, "path");
+
+#if DESKTOP || ANDROID || __IOS__ || MAC
+ return System.IO.Directory.Exists(path) ? new NET4FolderImplementation(path, true) : null;
+
+#elif CORE
+ return System.IO.Directory.Exists(path) ? new NETCOREFolderImplementation(path, true) : null;
+#endif
+
+ throw Exceptions.ExceptionsHelper.NotImplementedInReferenceAssembly();
+ }
+ }
+}
diff --git a/src/PCLExt.FileStorage.Portable/Folders/LocalFolder.cs b/src/PCLExt.FileStorage.Portable/Folders/LocalFolder.cs
new file mode 100644
index 0000000..62a2f62
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Folders/LocalFolder.cs
@@ -0,0 +1,51 @@
+namespace PCLExt.FileStorage.Folders
+{
+ ///
+ /// A folder representing storage which is local to the current device.
+ ///
+ public class LocalFolder : BaseFolder
+ {
+#if MAC
+ [System.Runtime.InteropServices.DllImport(ObjCRuntime.Constants.FoundationLibrary)]
+ static extern System.IntPtr NSHomeDirectory(); // Under the sandbox, need to read the HomeDirectory
+
+ static string MacHomeDirectory => ((Foundation.NSString)ObjCRuntime.Runtime.GetNSObject(NSHomeDirectory())).ToString();
+#endif
+
+ ///
+ ///
+ ///
+#if DESKTOP || ANDROID || __IOS__ || MAC
+ public LocalFolder() : base(GetLocalFolder()) { }
+ private static IFolder GetLocalFolder()
+ {
+#if ANDROID
+ var storage = Android.App.Application.Context.GetExternalFilesDir(null)?.ParentFile?.AbsolutePath;
+ if(string.IsNullOrEmpty(storage))
+ return null;
+#elif __IOS__
+ var documents = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
+ var storage = System.IO.Path.Combine(documents, "..", "Library");
+#elif MAC
+ // (non-sandboxed) /Users/foo/Library/Application Support/ProcessName/
+ // (sandboxed) /Users/foo/Library/Containers//Data/Library/Application Support/ProcessName/
+ var name = System.IO.Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().ProcessName);
+ var storage = System.IO.Path.Combine(MacHomeDirectory, "Library", "Application Support");
+ if(!string.IsNullOrEmpty(name))
+ {
+ storage = System.IO.Path.Combine(storage, name);
+ if(!System.IO.Directory.Exists(storage)) // Ensure it exists to stope FileSystemFolder from throwing exception.
+ System.IO.Directory.CreateDirectory(storage);
+ }
+#elif DESKTOP
+ var storage = System.Windows.Forms.Application.LocalUserAppDataPath; // SpecialFolder.LocalApplicationData is not app-specific, so use the Windows Forms API to get the app data path.
+#endif
+ return new NET4FolderImplementation(storage);
+ }
+#elif CORE
+ public LocalFolder() : base(null) => throw Exceptions.ExceptionsHelper.NotImplementedInNetStandard();
+#else
+ public LocalFolder() : base(null) => throw Exceptions.ExceptionsHelper.NotImplementedInReferenceAssembly();
+#endif
+ }
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage.Portable/Folders/RoamingFolder.cs b/src/PCLExt.FileStorage.Portable/Folders/RoamingFolder.cs
new file mode 100644
index 0000000..cb9be96
--- /dev/null
+++ b/src/PCLExt.FileStorage.Portable/Folders/RoamingFolder.cs
@@ -0,0 +1,32 @@
+namespace PCLExt.FileStorage.Folders
+{
+ ///
+ /// A folder representing storage which may be synced with other devices for the same user.
+ ///
+ public class RoamingFolder : BaseFolder
+ {
+ ///
+ ///
+ ///
+#if DESKTOP || ANDROID || __IOS__ || MAC
+ public RoamingFolder() : base(GetRoamingFolder()) { }
+ private static IFolder GetRoamingFolder()
+ {
+#if ANDROID
+ var storage = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
+
+#elif __IOS__ || MAC
+ var storage = "";
+ return null;
+#elif DESKTOP
+ var storage = System.Windows.Forms.Application.UserAppDataPath; // SpecialFolder.ApplicationData is not app-specific, so use the Windows Forms API to get the app data path.
+#endif
+ return new NET4FolderImplementation(storage);
+ }
+#elif CORE
+ public RoamingFolder() : base(null) => throw Exceptions.ExceptionsHelper.NotImplementedInNetStandard();
+#else
+ public RoamingFolder() : base(null) => throw Exceptions.ExceptionsHelper.NotImplementedInReferenceAssembly();
+#endif
+ }
+}
\ No newline at end of file
diff --git a/src/PCLExt.FileStorage/PCLExt.FileStorage.csproj b/src/PCLExt.FileStorage.Portable/PCLExt.FileStorage.Portable.csproj
similarity index 76%
rename from src/PCLExt.FileStorage/PCLExt.FileStorage.csproj
rename to src/PCLExt.FileStorage.Portable/PCLExt.FileStorage.Portable.csproj
index a86df7d..a3c2bf1 100644
--- a/src/PCLExt.FileStorage/PCLExt.FileStorage.csproj
+++ b/src/PCLExt.FileStorage.Portable/PCLExt.FileStorage.Portable.csproj
@@ -37,20 +37,26 @@
-
+
Properties\CommonAssemblyInfo.cs
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}
PCLExt.FileStorage.Abstractions
diff --git a/src/PCLExt.FileStorage/PortablePath.cs b/src/PCLExt.FileStorage.Portable/PortablePath.cs
similarity index 91%
rename from src/PCLExt.FileStorage/PortablePath.cs
rename to src/PCLExt.FileStorage.Portable/PortablePath.cs
index 8667019..4e2951d 100644
--- a/src/PCLExt.FileStorage/PortablePath.cs
+++ b/src/PCLExt.FileStorage.Portable/PortablePath.cs
@@ -7,6 +7,8 @@
// Which is released under the MS-PL license.
//-----------------------------------------------------------------------
+using PCLExt.FileStorage.Exceptions;
+
namespace PCLExt.FileStorage
{
///
@@ -25,7 +27,7 @@ public static char DirectorySeparatorChar
return System.IO.Path.DirectorySeparatorChar;
#endif
- throw FileSystem.NotImplementedInReferenceAssembly();
+ throw ExceptionsHelper.NotImplementedInReferenceAssembly();
}
}
@@ -40,7 +42,7 @@ public static string Combine(params string[] paths)
return System.IO.Path.Combine(paths);
#endif
- throw FileSystem.NotImplementedInReferenceAssembly();
+ throw ExceptionsHelper.NotImplementedInReferenceAssembly();
}
///
@@ -60,7 +62,7 @@ public static string GetExtension(string path)
return System.IO.Path.GetExtension(path);
#endif
- throw FileSystem.NotImplementedInReferenceAssembly();
+ throw ExceptionsHelper.NotImplementedInReferenceAssembly();
}
///
@@ -84,7 +86,7 @@ public static string GetFileName(string path)
return System.IO.Path.GetFileName(path);
#endif
- throw FileSystem.NotImplementedInReferenceAssembly();
+ throw ExceptionsHelper.NotImplementedInReferenceAssembly();
}
///
@@ -103,7 +105,7 @@ public static string GetFileNameWithoutExtension(string path)
return System.IO.Path.GetFileNameWithoutExtension(path);
#endif
- throw FileSystem.NotImplementedInReferenceAssembly();
+ throw ExceptionsHelper.NotImplementedInReferenceAssembly();
}
///
@@ -123,7 +125,7 @@ public static bool HasExtension(string path)
return System.IO.Path.HasExtension(path);
#endif
- throw FileSystem.NotImplementedInReferenceAssembly();
+ throw ExceptionsHelper.NotImplementedInReferenceAssembly();
}
}
}
diff --git a/src/PCLExt.FileStorage/Properties/AssemblyInfo.cs b/src/PCLExt.FileStorage.Portable/Properties/AssemblyInfo.cs
similarity index 100%
rename from src/PCLExt.FileStorage/Properties/AssemblyInfo.cs
rename to src/PCLExt.FileStorage.Portable/Properties/AssemblyInfo.cs
diff --git a/src/PCLExt.FileStorage/Requires.cs b/src/PCLExt.FileStorage.Portable/Requires.cs
similarity index 100%
rename from src/PCLExt.FileStorage/Requires.cs
rename to src/PCLExt.FileStorage.Portable/Requires.cs
diff --git a/src/PCLExt.FileStorage.iOS/PCLExt.FileStorage.iOS.csproj b/src/PCLExt.FileStorage.iOS/PCLExt.FileStorage.iOS.csproj
index 3223069..88c2362 100644
--- a/src/PCLExt.FileStorage.iOS/PCLExt.FileStorage.iOS.csproj
+++ b/src/PCLExt.FileStorage.iOS/PCLExt.FileStorage.iOS.csproj
@@ -37,46 +37,87 @@
-
-
+
Properties\CommonAssemblyInfo.cs
-
- DesktopFileSystem.cs
+
+ NET4FileImplementation.cs
-
- FileSystemFile.cs
+
+ NET4FolderImplementation.cs
-
- FileSystemFolder.cs
+
+ BaseFile.cs
-
- AwaitExtensions.cs
+
+ BaseFolder.cs
-
- PortablePath.cs
+
+ CreationCollisionOption.cs
-
- Requires.cs
+
+ ExistenceCheckResult.cs
-
- BaseFolder.cs
+
+ FolderSearchOption.cs
-
- BaseFile.cs
+
+ IFile.cs
-
-
- FileSystem.cs
+
+ IFolder.cs
+
+
+ NameCollisionOption.cs
+
+
+ Exceptions\DirectoryNotFoundException.cs
+
+
+ Exceptions\ExceptionsHelper.cs
+
+
+ Exceptions\FileNotFoundException.cs
+
+
+ Extensions\AwaitExtensions.cs
+
+ Extensions\FileExtensions.cs
+
+
+ Extensions\FolderExtensions.cs
+
+
+ Files\FileFromPath.cs
+
+
+ Folders\ApplicationFolder.cs
+
+
+ Folders\FolderFromPath.cs
+
+
+ Folders\LocalFolder.cs
+
+
+ Folders\RoamingFolder.cs
+
+
+ PortablePath.cs
+
+
+ Requires.cs
+
+
-
+
{3F8D0494-6EE2-47FE-B263-F09A5EA3D0B3}
PCLExt.FileStorage.Abstractions
diff --git a/src/PCLExt.FileStorage/FileSystem.cs b/src/PCLExt.FileStorage/FileSystem.cs
deleted file mode 100644
index 0c95b49..0000000
--- a/src/PCLExt.FileStorage/FileSystem.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-//-----------------------------------------------------------------------
-//
-// Copyright (c) Daniel Plaisted. All rights reserved.
-//
-// This file is a derivation of:
-// https://github.com/dsplaisted/PCLStorage
-// Which is released under the MS-PL license.
-//-----------------------------------------------------------------------
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace PCLExt.FileStorage
-{
- ///
- /// Provides access to an implementation of for the current platform.
- ///
- public static class FileSystem
- {
- internal static Exception NotImplementedInReferenceAssembly() =>
- new NotImplementedException(@"This functionality is not implemented in the portable version of this assembly.
-You should reference the PCLExt.FileStorage NuGet package from your main application project in order to reference the platform-specific implementation.");
-
-
- ///
- /// The implementation of for the current platform.
- ///
- private static IFileSystem Current
- {
- get
- {
-#if DESKTOP || ANDROID || __IOS__ || MAC
- return _fileSystem ?? (_fileSystem = new DesktopFileSystem());
-#endif
-
- throw NotImplementedInReferenceAssembly();
- }
- }
- private static IFileSystem _fileSystem;
-
-
-#if MAC
- [System.Runtime.InteropServices.DllImport(ObjCRuntime.Constants.FoundationLibrary)]
- static extern System.IntPtr NSHomeDirectory(); // Under the sandbox, need to read the HomeDirectory
-
- static string MacHomeDirectory => ((Foundation.NSString)ObjCRuntime.Runtime.GetNSObject(NSHomeDirectory())).ToString();
-#endif
-
- ///
- /// A folder representing storage which is where the app is running.
- ///
- public static IFolder BaseStorage => Current.BaseStorage;
-
- ///
- /// A folder representing storage which is local to the current device.
- ///
- public static IFolder LocalStorage => Current.LocalStorage;
-
- ///
- /// A folder representing storage which may be synced with other devices for the same user.
- ///
- public static IFolder RoamingStorage => Current.RoamingStorage;
-
- ///
- /// A folder representing storage which may be synced with other devices for the same user.
- ///
- public static IFolder SpecialStorage => Current.SpecialStorage;
-
-
-
-
- ///
- /// Gets a file, given its path. Returns null if the file does not exist.
- ///
- /// The path to a file, as returned from the property.
- /// A file for the given path, or null if it does not exist.
- public static IFile GetFileFromPath(string path)
- {
- Requires.NotNullOrEmpty(path, "path");
-
-#if DESKTOP || ANDROID || __IOS__ || MAC
- if (System.IO.File.Exists(path))
- return new FileSystemFile(path);
-
- return null;
-#endif
-
- throw NotImplementedInReferenceAssembly();
- }
-
- ///
- /// Gets a file, given its path. Returns null if the file does not exist.
- ///
- /// The path to a file, as returned from the property.
- /// The cancellation token.
- /// A file for the given path, or null if it does not exist.
- public static async Task GetFileFromPathAsync(string path, CancellationToken cancellationToken)
- {
- Requires.NotNullOrEmpty(path, "path");
-
-#if DESKTOP || ANDROID || __IOS__ || MAC
- await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
- if (System.IO.File.Exists(path))
- return new FileSystemFile(path);
-
- return null;
-#endif
-
- throw NotImplementedInReferenceAssembly();
- }
-
- ///
- /// Gets a folder, given its path. Returns null if the folder does not exist.
- ///
- /// The path to a folder, as returned from the property.
- /// A folder for the specified path, or null if it does not exist.
- public static IFolder GetFolderFromPath(string path)
- {
- Requires.NotNullOrEmpty(path, "path");
-
-#if DESKTOP || ANDROID || __IOS__ || MAC
- if (System.IO.Directory.Exists(path))
- return new FileSystemFolder(path, true);
-
- return null;
-#endif
-
- throw NotImplementedInReferenceAssembly();
- }
-
- ///
- /// Gets a folder, given its path. Returns null if the folder does not exist.
- ///
- /// The path to a folder, as returned from the property.
- /// The cancellation token.
- /// A folder for the specified path, or null if it does not exist.
- public static async Task GetFolderFromPathAsync(string path, CancellationToken cancellationToken)
- {
- Requires.NotNullOrEmpty(path, "path");
-
-#if DESKTOP || ANDROID || __IOS__ || MAC
- await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken);
- if (System.IO.Directory.Exists(path))
- return new FileSystemFolder(path, true);
-
- return null;
-#endif
-
- throw NotImplementedInReferenceAssembly();
- }
- }
-}