The accepted answer is good, but setting a private member to Console.Out felt like a bit of a hack so I decided to go further. Turns out you don't really need the reference to originalOut at all, but rather just need to call the base methods in your overrides. Here is my complete example using StreamWriter as the base (also a .NET 8 project with Nullable enabled).
public class DatePrefixWriter(string filename, FileStreamOptions fsopts) : StreamWriter(filename, fsopts)
{
private bool atLineStart = true;
public override System.Text.Encoding Encoding
{
get { return new System.Text.ASCIIEncoding(); }
}
public override void WriteLine(string? message)
{
this.Write(string.Format("{0}{1}", message, this.NewLine));
}
public override void Write(string? message)
{
if(atLineStart) //I want to ensure timestamps are only written once per line
base.Write(string.Format("{0}> {1} ", DateTime.Now, message));
else
base.Write(message);
atLineStart = message?.EndsWith(NewLine) ?? atLineStart;
}
}
You can configure the writer in the Program main() with the code below. Another advantage to the method above is that the same class can be used with Console.SetError()
Console.SetOut(
new DatePrefixWriter(logFileName, new FileStreamOptions() {
Mode = FileMode.Append,
Access = FileAccess.Write
}) { AutoFlush = true }
);