如何修改System.Console.WriteLine方法实现控制台与日志双输出?
解决方案:同时输出控制台与日志的简便实现
针对你遇到的Console静态类无法继承、重载过多的问题,最优解是利用.NET的Console.SetOut方法重定向输出流,无需手动实现18个重载,就能让所有Console.WriteLine调用自动同时写入日志和控制台。
方法一:自定义输出流(推荐)
通过继承TextWriter实现一个同时处理日志和原生控制台输出的自定义流,然后替换Console的默认输出流即可。
步骤1:实现自定义Writer类
using System.IO; using System.Text; public class ConsoleAndLogWriter : TextWriter { private readonly TextWriter _originalConsoleOut; private readonly string _logFileName; public ConsoleAndLogWriter(string logFileName) { _originalConsoleOut = Console.Out; _logFileName = logFileName; } // 必须重写Encoding属性 public override Encoding Encoding => _originalConsoleOut.Encoding; // 处理所有文本输出(覆盖基础写入逻辑,自动适配所有Write/WriteLine重载) public override void Write(char[] buffer, int index, int count) { string outputText = new string(buffer, index, count); // 过滤空行(可选,根据需求调整) if (!string.IsNullOrWhiteSpace(outputText.TrimEnd('\r', '\n'))) { Logger.WriteLog(outputText.TrimEnd('\r', '\n'), _logFileName); } // 输出到原生控制台 _originalConsoleOut.Write(buffer, index, count); } // 可选:单独处理无参WriteLine,避免空行日志 public override void WriteLine() { _originalConsoleOut.WriteLine(); } }
步骤2:程序启动时替换输出流
在程序入口(比如Main方法开头)执行以下代码,之后所有Console.WriteLine都会自动同步日志:
// 初始化自定义输出流,指定日志文件名 Console.SetOut(new ConsoleAndLogWriter("MyApplicationLog")); // 测试调用 Console.WriteLine("Hello World!"); Console.WriteLine(123); Console.WriteLine(true);
方法二:反射包装类(备选)
如果不想重定向输出流,可以用反射动态调用Console的重载方法,同时触发日志写入。这种方式需要替换原有代码中的Console为自定义静态类,但无需手动实现所有重载:
using System.Reflection; public static class LoggingConsole { private static readonly Type _consoleType = typeof(Console); private const string DefaultLogFileName = "MyAppLog"; public static void WriteLine(params object[] args) { // 生成日志文本 string logText = args.Length == 0 ? string.Empty : string.Join(" ", args); Logger.WriteLog(logText, DefaultLogFileName); // 反射调用对应重载的Console.WriteLine MethodInfo method; if (args.Length == 0) { method = _consoleType.GetMethod("WriteLine", Type.EmptyTypes); } else { Type[] argTypes = args.Select(a => a.GetType()).ToArray(); method = _consoleType.GetMethod("WriteLine", argTypes); } method?.Invoke(null, args); } }
使用示例
LoggingConsole.WriteLine("Hello World!"); LoggingConsole.WriteLine("Number:", 123);
对现有Logger的小优化
你的Logger.WriteLog方法中,Path.GetTempPath()返回的系统临时目录必然存在,因此可以去掉Directory.Exists的判断,简化代码:
// 原代码中这部分可以删除 // if (!Directory.Exists(destPath)) // Directory.CreateDirectory(destPath);
内容的提问来源于stack exchange,提问作者user2838376
相关产品推荐
相关产品推荐

