C# WinForms 日志实现与封装
C# WinForms 日志实现与封装
下面我将为您实现一个完整的、可重用的日志系统,适用于WinForms应用程序。这个实现包括文件日志、控制台日志和WinForms文本框日志输出,并提供了简单的接口供后续项目直接引用。
1. 创建日志接口和基础实现
首先,我们定义一个日志接口,然后提供几种实现方式。
using System;namespace WinFormsLogger
{// 日志级别枚举public enum LogLevel{Debug,Info,Warning,Error,Fatal}// 日志接口public interface ILogger{void Log(LogLevel level, string message);void Debug(string message);void Info(string message);void Warning(string message);void Error(string message);void Fatal(string message);}// 抽象基类提供默认实现public abstract class LoggerBase : ILogger{public virtual void Debug(string message) => Log(LogLevel.Debug, message);public virtual void Info(string message) => Log(LogLevel.Info, message);public virtual void Warning(string message) => Log(LogLevel.Warning, message);public virtual void Error(string message) => Log(LogLevel.Error, message);public virtual void Fatal(string message) => Log(LogLevel.Fatal, message);public abstract void Log(LogLevel level, string message);protected virtual string FormatMessage(LogLevel level, string message){return $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} [{level}] {message}";}}
}
2. 实现具体的日志记录器
2.1 文件日志记录器
using System;
using System.IO;namespace WinFormsLogger
{public class FileLogger : LoggerBase{private readonly string _logFilePath;private readonly object _lock = new object();public FileLogger(string logFilePath){_logFilePath = logFilePath;// 确保日志目录存在var dir = Path.GetDirectoryName(_logFilePath);if (!string.IsNullOrEmpty(dir) Directory.CreateDirectory(dir);}public override void Log(LogLevel level, string message){lock (_lock){File.AppendAllText(_logFilePath, FormatMessage(level, message) + Environment.NewLine);}}}
}
2.2 控制台日志记录器
using System;namespace WinFormsLogger
{public class ConsoleLogger : LoggerBase{public override void Log(LogLevel level, string message){var originalColor = Console.ForegroundColor;try{Console.ForegroundColor = GetLevelColor(level);Console.WriteLine(FormatMessage(level, message));}finally{Console.ForegroundColor = originalColor;}}private ConsoleColor GetLevelColor(LogLevel level){return level switch{LogLevel.Debug => ConsoleColor.Gray,LogLevel.Info => ConsoleColor.White,LogLevel.Warning => ConsoleColor.Yellow,LogLevel.Error => ConsoleColor.Red,LogLevel.Fatal => ConsoleColor.DarkRed,_ => ConsoleColor.White};}}
}
2.3 WinForms文本框日志记录器
using System;
using System.Windows.Forms;namespace WinFormsLogger
{public class TextBoxLogger : LoggerBase{private readonly TextBox _textBox;private readonly int _maxLines;public TextBoxLogger(TextBox textBox, int maxLines = 1000){_textBox = textBox ?? throw new ArgumentNullException(nameof(textBox));_maxLines = maxLines;}public override void Log(LogLevel level, string message){if (_textBox.InvokeRequired){_textBox.Invoke(new Action(() => Log(level, message)));return;}var formattedMessage = FormatMessage(level, message);_textBox.AppendText(formattedMessage + Environment.NewLine);// 限制最大行数if (_textBox.Lines.Length > _maxLines){var lines = _textBox.Lines;var newLines = new string[Math.Min(_maxLines, lines.Length)];Array.Copy(lines, lines.Length - newLines.Length, newLines, 0, newLines.Length);_textBox.Lines = newLines;}_textBox.ScrollToCaret();}}
}
2.4 复合日志记录器(可同时记录到多个目标)
using System;
using System.Collections.Generic;namespace WinFormsLogger
{public class CompositeLogger : LoggerBase{private readonly List<ILogger> _loggers = new List<ILogger>();public void AddLogger(ILogger logger){if (logger == null) throw new ArgumentNullException(nameof(logger));_loggers.Add(logger);}public override void Log(LogLevel level, string message){foreach (var logger in _loggers){logger.Log(level, message);}}}
}
3. 日志管理器(便于全局访问)
using System;namespace WinFormsLogger
{public static class LogManager{private static ILogger _logger = new ConsoleLogger(); // 默认使用控制台日志public static ILogger Logger{get => _logger;set => _logger = value ?? throw new ArgumentNullException(nameof(value));}public static void Debug(string message) => Logger.Debug(message);public static void Info(string message) => Logger.Info(message);public static void Warning(string message) => Logger.Warning(message);public static void Error(string message) => Logger.Error(message);public static void Fatal(string message) => Logger.Fatal(message);}
}
4. 使用示例
4.1 在WinForms项目中初始化日志系统
using System;
using System.Windows.Forms;
using WinFormsLogger;namespace YourWinFormsApp
{public partial class MainForm : Form{public MainForm(){InitializeComponent();InitializeLogging();}private void InitializeLogging(){// 创建复合日志记录器var compositeLogger = new CompositeLogger();// 添加文件日志记录器compositeLogger.AddLogger(new FileLogger("logs/application.log"));// 添加控制台日志记录器(调试时有用)compositeLogger.AddLogger(new ConsoleLogger());// 添加文本框日志记录器(假设你的窗体上有一个名为txtLog的TextBox)compositeLogger.AddLogger(new TextBoxLogger(txtLog));// 设置为全局日志记录器LogManager.Logger = compositeLogger;LogManager.Info("日志系统初始化完成");}private void btnDoSomething_Click(object sender, EventArgs e){try{LogManager.Debug("开始执行某些操作...");// 你的业务逻辑代码LogManager.Info("操作成功完成");}catch (Exception ex){LogManager.Error($"操作失败: {ex.Message}");}}}
}
4.2 在其他类中使用日志
using WinFormsLogger;namespace YourWinFormsApp
{public class SomeService{public void PerformTask(){LogManager.Info("开始执行任务...");try{// 业务逻辑LogManager.Debug("任务执行中...");}catch (Exception ex){LogManager.Error($"任务执行出错: {ex}");throw;}LogManager.Info("任务完成");}}
}
5. 高级功能扩展
如果您需要更高级的功能,可以考虑以下扩展:
5.1 日志文件滚动
修改FileLogger
类,实现日志文件按日期或大小滚动:
public class RollingFileLogger : LoggerBase
{private readonly string _logDirectory;private readonly string _logFileBaseName;private readonly long _maxFileSize;private readonly int _maxBackupFiles;private readonly object _lock = new object();private string _currentLogFilePath;public RollingFileLogger(string logDirectory, string logFileBaseName, long maxFileSize = 10 * 1024 * 1024, // 默认10MBint maxBackupFiles = 10){_logDirectory = logDirectory;_logFileBaseName = logFileBaseName;_maxFileSize = maxFileSize;_maxBackupFiles = maxBackupFiles;Directory.CreateDirectory(_logDirectory);_currentLogFilePath = GetCurrentLogFilePath();}private string GetCurrentLogFilePath(){return Path.Combine(_logDirectory, $"{_logFileBaseName}_{DateTime.Now:yyyyMMdd}.log");}public override void Log(LogLevel level, string message){lock (_lock){var currentDate = DateTime.Now.Date;var newLogFilePath = GetCurrentLogFilePath();// 如果日期变化或文件过大,滚动日志if (newLogFilePath != _currentLogFilePath || (File.Exists(_currentLogFilePath) && new FileInfo(_currentLogFilePath).Length > _maxFileSize)){RollLogFiles();_currentLogFilePath = newLogFilePath;}File.AppendAllText(_currentLogFilePath, FormatMessage(level, message) + Environment.NewLine);}}private void RollLogFiles(){// 实现日志文件滚动逻辑// ...}
}
5.2 异步日志记录
using System;
using System.Threading.Tasks;namespace WinFormsLogger
{public class AsyncLogger : LoggerBase{private readonly ILogger _innerLogger;private readonly TaskQueue _taskQueue;public AsyncLogger(ILogger innerLogger){_innerLogger = innerLogger ?? throw new ArgumentNullException(nameof(innerLogger));_taskQueue = new TaskQueue();}public override void Log(LogLevel level, string message){_taskQueue.Enqueue(() => _innerLogger.Log(level, message));}// 简单的任务队列实现private class TaskQueue{private readonly object _lock = new object();private Task _lastTask = Task.CompletedTask;public void Enqueue(Action action){lock (_lock){_lastTask = _lastTask.ContinueWith(_ => action(), TaskContinuationOptions.ExecuteSynchronously);}}}}
}
6. 打包为可重用的类库
要将这个日志系统打包为可重用的类库:
- 创建一个新的"类库(.NET Framework)"或"类库(.NET Standard)"项目
- 将上述代码文件添加到项目中
- 编译生成DLL
- 在其他WinForms项目中引用此DLL
总结
这个日志系统提供了以下特点:
- 灵活:支持多种日志输出目标(文件、控制台、文本框)
- 可扩展:可以轻松添加新的日志记录器实现
- 线程安全:所有日志记录器都考虑了线程安全
- 简单易用:通过
LogManager
静态类提供全局访问 - 可重用:可以打包为独立的类库供多个项目使用