Content Reader/Writer, StreamCopyCommandHandler

This commit is contained in:
2022-06-09 06:59:53 +02:00
parent e947282d7b
commit 6d9bf7ab32
27 changed files with 494 additions and 27 deletions

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FileTime.Core.Abstraction\FileTime.Core.Abstraction.csproj" />
<ProjectReference Include="..\FileTime.Core.Command\FileTime.Core.Command.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
using FileTime.Core.Command;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.Core.CommandHandlers;
public static class Startup
{
public static IServiceCollection AddDefaultCommandHandlers(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddSingleton<ICommandHandler, StreamCopyCommandHandler>();
}
}

View File

@@ -0,0 +1,85 @@
using FileTime.Core.Command;
using FileTime.Core.Command.Copy;
using FileTime.Core.ContentAccess;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
namespace FileTime.Core.CommandHandlers;
public class StreamCopyCommandHandler : ICommandHandler
{
private readonly IContentProviderRegistry _contentProviderRegistry;
private readonly IContentAccessorFactory _contentAccessorFactory;
public StreamCopyCommandHandler(
IContentProviderRegistry contentProviderRegistry,
IContentAccessorFactory contentAccessorFactory)
{
_contentProviderRegistry = contentProviderRegistry;
_contentAccessorFactory = contentAccessorFactory;
}
public bool CanHandle(ICommand command)
{
if (command is not CopyCommand copyCommand) return false;
var targetSupportsContentStream =
_contentProviderRegistry
.ContentProviders
.FirstOrDefault(p => p.CanHandlePath(copyCommand.Target!))
?.SupportsContentStreams ?? false;
var allSourcesSupportsContentStream =
copyCommand
.Sources
.Select(s =>
_contentProviderRegistry
.ContentProviders
.FirstOrDefault(p => p.CanHandlePath(s))
)
.All(p => p?.SupportsContentStreams ?? false);
return targetSupportsContentStream && allSourcesSupportsContentStream;
}
public async Task ExecuteAsync(ICommand command)
{
if (command is not CopyCommand copyCommand) throw new ArgumentException($"Can not execute command of type '{command.GetType()}'.");
await copyCommand.ExecuteAsync(CopyElement);
}
public async Task CopyElement(AbsolutePath sourcePath, AbsolutePath targetPath, CopyCommandContext copyCommandContext)
{
var parent = (IContainer?) (await targetPath.GetParent()!.ResolveAsync())!;
var elementName = targetPath.Path;
var parentChildren = await parent.Items.GetItemsAsync();
if (parentChildren!.All(e => e.Path.GetName() != elementName.GetName()))
{
var itemCreator = _contentAccessorFactory.GetItemCreator(parent.Provider);
await itemCreator.CreateElementAsync(parent.Provider, elementName);
}
var source = (IElement?) (await sourcePath.ResolveAsync())!;
var target = (IElement?) (await targetPath.ResolveAsync())!;
using var reader = await _contentAccessorFactory.GetContentReaderFactory(source.Provider).CreateContentReaderAsync(source);
using var writer = await _contentAccessorFactory.GetContentWriterFactory(target.Provider).CreateContentWriterAsync(target);
byte[] dataRead;
var currentProgress = 0L;
do
{
dataRead = await reader.ReadBytesAsync(writer.PreferredBufferSize);
if (dataRead.Length > 0)
{
await writer.WriteBytesAsync(dataRead);
await writer.FlushAsync();
currentProgress += dataRead.LongLength;
copyCommandContext.CurrentProgress?.SetProgress(currentProgress);
await copyCommandContext.UpdateProgress();
}
} while (dataRead.Length > 0);
}
}