199 lines
4.2 KiB
C#
199 lines
4.2 KiB
C#
using ReportGenerator.Generator.Interface;
|
|
using System.Text;
|
|
|
|
namespace ReportGenerator.Generator.Abstract;
|
|
|
|
public abstract class StreamWriterBase : IStreamWriter
|
|
{
|
|
private bool _isOpen;
|
|
private bool _isClosed;
|
|
|
|
/// <summary>
|
|
/// Underlying <see cref="Stream"/>
|
|
/// </summary>
|
|
private Stream Stream { get; }
|
|
|
|
/// <summary>
|
|
/// Internal <see cref="StreamWriter"/> for generating the output <see cref="string"/>
|
|
/// </summary>
|
|
protected TextWriter Writer { get; }
|
|
|
|
/// <summary>
|
|
/// Constructor; Configures the
|
|
/// <see cref="StreamWriterBase"/> to write to the memory
|
|
/// </summary>
|
|
protected StreamWriterBase() : this(new MemoryStream()) { }
|
|
|
|
/// <inheritdoc cref="StreamWriterBase(System.IO.Stream, Encoding)"/>
|
|
protected StreamWriterBase(Stream stream) : this(stream, Encoding.UTF8) { }
|
|
|
|
/// <summary>
|
|
/// Constructor; Configures the <see cref="StreamWriterBase"/>
|
|
/// to write to the specified <paramref name="stream"/>
|
|
/// </summary>
|
|
/// <param name="stream">The <see cref="Stream"/> to write to</param>
|
|
/// <param name="encoding">Text <see cref="Encoding"/> of the written data</param>
|
|
protected StreamWriterBase(Stream stream, Encoding encoding)
|
|
{
|
|
Stream = stream;
|
|
Writer = new StreamWriter(stream, encoding);
|
|
}
|
|
|
|
#region Control
|
|
|
|
public void Open()
|
|
{
|
|
if (_isOpen)
|
|
{
|
|
throw new InvalidOperationException($"{GetType()} has already been opened");
|
|
}
|
|
|
|
if (_isClosed)
|
|
{
|
|
throw new InvalidOperationException($"Cannot call open on a closed {GetType()}");
|
|
}
|
|
|
|
_isOpen = true;
|
|
|
|
OnOpen();
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
if (_isClosed)
|
|
{
|
|
throw new InvalidOperationException($"{GetType()} has already been closed");
|
|
}
|
|
|
|
if (!_isOpen)
|
|
{
|
|
throw new InvalidOperationException($"{GetType()} has never been opened");
|
|
}
|
|
|
|
_isClosed = true;
|
|
|
|
OnClose();
|
|
Writer.Flush();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called once the internal writer has been initialized
|
|
/// and the <see cref="Stream"/> is ready for writing
|
|
/// </summary>
|
|
protected virtual void OnOpen() { }
|
|
|
|
/// <summary>
|
|
/// Called once the document is about to be closed
|
|
/// </summary>
|
|
protected virtual void OnClose() { }
|
|
|
|
#endregion
|
|
|
|
#region Reading
|
|
|
|
/// <inheritdoc />
|
|
public StreamReader Read()
|
|
{
|
|
Writer.Flush();
|
|
Stream.Seek(0, SeekOrigin.Begin);
|
|
return new StreamReader(Stream, Writer.Encoding);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Writing
|
|
|
|
public IStreamWriter Write(IStreamWriter writer)
|
|
{
|
|
using var reader = writer.Read();
|
|
return Write(reader);
|
|
}
|
|
|
|
public IStreamWriter Write(StreamReader reader)
|
|
{
|
|
int bytesRead;
|
|
char[] buffer = new char[4096];
|
|
|
|
while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
|
|
{
|
|
Writer.Write(buffer, 0, bytesRead);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public IStreamWriter Write(string? text = default)
|
|
{
|
|
Writer.Write(text);
|
|
return this;
|
|
}
|
|
|
|
public IStreamWriter WriteLine(string? text = default)
|
|
{
|
|
Writer.WriteLine(text);
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and configures the <typeparamref name="T"/> using the given functions
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the <see cref="IStreamWriter"/></typeparam>
|
|
/// <param name="makeFunc">Function used to generate the <typeparamref name="T"/></param>
|
|
/// <param name="configFunc">Function used to configure the <typeparamref name="T"/></param>
|
|
/// <returns></returns>
|
|
public IStreamWriter Write<T>(Func<T> makeFunc, Action<T> configFunc)
|
|
where T : IStreamWriter
|
|
{
|
|
using var writer = makeFunc();
|
|
|
|
writer.Open();
|
|
configFunc(writer);
|
|
writer.Close();
|
|
|
|
Write(writer);
|
|
return this;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDisposable
|
|
|
|
private bool _disposed;
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
try
|
|
{
|
|
// Close document
|
|
Close();
|
|
}
|
|
catch (InvalidOperationException)
|
|
{
|
|
// ignore
|
|
}
|
|
finally
|
|
{
|
|
// Dispose stream
|
|
Stream.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_disposed = true;
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
#endregion
|
|
}
|