< Summary

Information
Class: ArturRios.Data.Export.Exporters.ExporterBase<T>
Assembly: ArturRios.Data.Export
File(s): D:\Repositories\dotnet-data\src\ArturRios.Data.Export\Exporters\ExporterBase.cs
Line coverage
86%
Covered lines: 19
Uncovered lines: 3
Coverable lines: 22
Total lines: 57
Line coverage: 86.3%
Branch coverage
75%
Covered branches: 6
Total branches: 8
Branch coverage: 75%
Method coverage
100%
Covered methods: 4
Fully covered methods: 2
Total methods: 4
Method coverage: 100%
Full method coverage: 50%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
WriteAsync(...)100%11100%
WriteToFileAsync(...)100%11100%
GuardedWriteAsync()100%44100%
GuardedFileAsync()50%4472.72%

File(s)

D:\Repositories\dotnet-data\src\ArturRios.Data.Export\Exporters\ExporterBase.cs

#LineLine coverage
 1using ArturRios.Data.Export.Interfaces;
 2using ArturRios.Output;
 3
 4namespace ArturRios.Data.Export.Exporters;
 5
 6/// <summary>
 7///     Base for exporters: handles null-guarding, envelope conversion, cancellation propagation, and
 8///     file-stream lifetime. Concrete exporters implement <see cref="WriteCoreAsync" />.
 9/// </summary>
 10/// <typeparam name="T">The record type.</typeparam>
 11public abstract class ExporterBase<T> : IExporter<T> where T : class
 12{
 13    /// <summary>Prefix for enveloped error messages.</summary>
 14    protected const string ExportFailedMessage = "An export error occurred:";
 15
 16    /// <inheritdoc />
 17    public Task<ProcessOutput> WriteAsync(IEnumerable<T> data, Stream destination, CancellationToken ct = default) =>
 4018        GuardedWriteAsync(data, destination, stream => WriteCoreAsync(data, stream, ct));
 19
 20    /// <inheritdoc />
 21    public Task<ProcessOutput> WriteToFileAsync(IEnumerable<T> data, string path, CancellationToken ct = default) =>
 222        GuardedFileAsync(data, path, stream => WriteCoreAsync(data, stream, ct));
 23
 24    /// <summary>Guards a stream write: null checks, envelope conversion, cancellation propagation.</summary>
 25    protected async Task<ProcessOutput> GuardedWriteAsync(IEnumerable<T> data, Stream destination, Func<Stream, Task> wr
 2326    {
 2527        if (data is null) return ProcessOutput.New.WithError($"{ExportFailedMessage} data is null.");
 2228        if (destination is null) return ProcessOutput.New.WithError($"{ExportFailedMessage} destination is null.");
 29
 30        try
 2031        {
 2032            await write(destination);
 1833            return ProcessOutput.New;
 34        }
 335        catch (OperationCanceledException) { throw; }
 336        catch (Exception ex) { return ProcessOutput.New.WithError($"{ExportFailedMessage} {ex.GetBaseException().Message
 2237    }
 38
 39    /// <summary>Guards a file write: opens/truncates the file, then delegates to <paramref name="write" />.</summary>
 40    protected async Task<ProcessOutput> GuardedFileAsync(IEnumerable<T> data, string path, Func<Stream, Task> write)
 141    {
 142        if (data is null) return ProcessOutput.New.WithError($"{ExportFailedMessage} data is null.");
 143        if (string.IsNullOrEmpty(path)) return ProcessOutput.New.WithError($"{ExportFailedMessage} path is null or empty
 44
 45        try
 146        {
 147            await using var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
 148            await write(stream);
 149            return ProcessOutput.New;
 050        }
 051        catch (OperationCanceledException) { throw; }
 052        catch (Exception ex) { return ProcessOutput.New.WithError($"{ExportFailedMessage} {ex.GetBaseException().Message
 153    }
 54
 55    /// <summary>Format-specific write. Implementations must honor <paramref name="ct" /> and not dispose the stream.</s
 56    protected abstract Task WriteCoreAsync(IEnumerable<T> data, Stream destination, CancellationToken ct);
 57}