using ReportGenerator.Generator.Interface; using System.Text; namespace ReportGenerator.Generator.Abstract; public abstract class StreamWriterBase : IStreamWriter { private bool _isOpen; private bool _isClosed; /// /// Underlying /// private Stream Stream { get; } /// /// Internal for generating the output /// protected TextWriter Writer { get; } /// /// Constructor; Configures the /// to write to the memory /// protected StreamWriterBase() : this(new MemoryStream()) { } /// protected StreamWriterBase(Stream stream) : this(stream, Encoding.UTF8) { } /// /// Constructor; Configures the /// to write to the specified /// /// The to write to /// Text of the written data 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(); } /// /// Called once the internal writer has been initialized /// and the is ready for writing /// protected virtual void OnOpen() { } /// /// Called once the document is about to be closed /// protected virtual void OnClose() { } #endregion #region Reading /// 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; } /// /// Creates and configures the using the given functions /// /// Type of the /// Function used to generate the /// Function used to configure the /// public IStreamWriter Write(Func makeFunc, Action 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(); } } } /// public void Dispose() { if (_disposed) { return; } _disposed = true; Dispose(true); GC.SuppressFinalize(this); } #endregion }