Расширения для работы с внешними источниками файлов.
Расширения для работы с внешними источниками файлов.¶
Имеется возможность обрабатывать файлы из внешних систем (электронные хранилища, облачные сервисы и прочее). Для ознакомления с этой возможностью существуют специальные демонстрационные расширения в рамках карточки “Автомобиль”.
Пункт меню “Файлы из внешней системы” включает отображение файлов из внешней системы (для демонстрации файлы предоставляются виртуально). Так же в список группировок добавляется группировка по типу источника файлов (которая автоматически применяется к текущему списку файлов), а в список фильтров добавляются соответствующие фильтры по типу источника файлов. Повторное использование этого пункта меню отключает отображение внешних файлов.
Для файлов из внешнего источника возможны только операции: чтения, получения списка версий и Сохранения на диск.
Принцип работы основан на добавлении в карточку виртуальных файлов, источником для которых является внешняя система. Для этого необходимо создать наследников FileSource’а, File’а и FileCreationToken’а и переопределить им некоторые методы.
В наследниках File’а и FileCreationToken’а можно добавить необходимые новые свойства.
public class ExternalFileCreationToken : FileCreationToken
{
public string Description { get; set; }
}
public class ExternalFile : File
{
public ExternalFile(
Guid id,
string name,
long size,
IFileCategory category,
IFileType type,
IFileContent content,
ExternalFileSource source,
IFilePermissions permissions = null,
bool isLocal = true,
IFile origin = null,
string description = null)
: base(
id,
name,
size,
category,
type,
content,
source,
permissions,
isLocal,
origin)
{
this.Description = description;
}
public string Description { get; protected set; }
public Task SetDescriptionAsync(
string value,
Func<Action, CancellationToken, Task> executePropertyChangedAsync = null,
CancellationToken cancellationToken = default)
{
if (this.Description == value)
{
return Task.CompletedTask;
}
this.Description = value;
if (executePropertyChangedAsync is null)
{
this.OnPropertyChanged(nameof(this.Description));
return Task.CompletedTask;
}
return executePropertyChangedAsync(() => this.OnPropertyChanged(nameof(this.Description)), cancellationToken);
}
}
В наследнике FileSource’а переопределяется реализация методов CreateFileCore и GetFileCreationTokenCore. Это необходимо, чтобы иметь возможность создать (и в последствии добавить в список файлов) файл внешнего типа.
protected override async ValueTask<IFile> CreateFileCoreAsync(
IFileCreationToken token,
IFileContent content = null,
CancellationToken cancellationToken = default)
{
// здесь возможно исключение, связанное с параметрами метода
var typedToken = (ExternalFileCreationToken)token;
string name = token.Name;
IFileContent allocatedContent = null;
IFileContent actualContent = content
?? (allocatedContent = await this.Cache.AllocateAsync(name, cancellationToken: cancellationToken).ConfigureAwait(false));
try
{
// все свойства токена проверяются в конструкторе
return new ExternalFile(
token.ID ?? Guid.NewGuid(),
name,
token.Size,
token.Category,
token.Type,
actualContent,
this,
token.Permissions.Clone(),
token.IsLocal,
description: typedToken.Description);
}
catch (Exception)
{
if (allocatedContent != null)
{
await allocatedContent.DisposeAsync().ConfigureAwait(false);
}
throw;
}
}
protected override async ValueTask<IFileCreationToken> GetFileCreationTokenCoreAsync(
CancellationToken cancellationToken = default) =>
new ExternalFileCreationToken();
Также необходимо переопределить метод GetContentCore. Этот метод отвечает за получение содержимого файлов. Именно в этом методе необходимо выполнять запрос к внешнему источнику файлов. В данном примере содержимое формируется на основе свойства “Description”.
protected override async ValueTask<IFileContentResponse> GetContentCoreAsync(
IFileContentRequest request,
CancellationToken cancellationToken = default)
{
string content = ((ExternalFile) request.Version.File).Description ?? string.Empty;
await using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)))
{
Func<Stream, CancellationToken, ValueTask> processContentActionAsync =
request.ProcessContentActionAsync ?? ((s, ct2) => new ValueTask());
await processContentActionAsync(stream, cancellationToken).ConfigureAwait(false);
}
return new FileContentResponse(request.Version);
}
Note
Все необходимые расширения и примеры кода находятся в Tessa.Extensions.Default.Client.ExternalFiles.