You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF通用日志添加函数开发:同步Log4Net与ObservableCollection日志

没问题,我给你整理一个干净利落的解决方案,一次性搞定Log4Net日志写入和ObservableCollection的更新!

核心思路

我们要封装一个静态日志助手类,把Log4Net的日志记录逻辑和ObservableCollection的更新逻辑整合到一起,对外暴露和Log4Net用法一致的快捷方法(比如Info、Error),这样你只需要调用一次助手类的方法,就能同时完成两个操作。

完整代码实现

首先确保你已经定义了LogEntry类(如果还没完善,可以参考下面的示例):

public class LogEntry
{
    public Level Level { get; set; }
    public string Message { get; set; }
    public string Source { get; set; }
    public DateTime Timestamp { get; set; }
    // 可以根据需求添加更多属性,比如线程ID、异常详情等
}

然后是核心的日志助手类:

using log4net;
using log4net.Core;
using System;
using System.Collections.ObjectModel;
using System.Windows;

public static class LogHelper
{
    // 初始化Log4Net日志实例,默认取当前类作为日志源
    private static readonly ILog _log = LogManager.GetLogger(typeof(LogHelper));
    
    // 全局可观测日志集合,确保初始化完成
    public static ObservableCollection<LogEntry> LogEntries { get; set; } = new ObservableCollection<LogEntry>();

    // 私有核心方法:统一处理日志记录和集合更新
    private static void Log(Level level, string message, string source = null, Exception ex = null)
    {
        // 第一步:调用Log4Net写入文本日志
        switch (level)
        {
            case Level.Info:
                if (ex == null) _log.Info(message);
                else _log.Info(message, ex);
                break;
            case Level.Debug:
                if (ex == null) _log.Debug(message);
                else _log.Debug(message, ex);
                break;
            case Level.Warn:
                if (ex == null) _log.Warn(message);
                else _log.Warn(message, ex);
                break;
            case Level.Error:
                if (ex == null) _log.Error(message);
                else _log.Error(message, ex);
                break;
            case Level.Fatal:
                if (ex == null) _log.Fatal(message);
                else _log.Fatal(message, ex);
                break;
            default:
                _log.Info(message);
                break;
        }

        // 第二步:更新ObservableCollection,确保在UI线程操作
        if (LogEntries != null && Application.Current != null)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                var logEntry = new LogEntry
                {
                    Level = level,
                    Message = ex == null ? message : $"{message}\n异常详情:{ex.ToString()}",
                    Source = source ?? _log.Logger.Name, // 默认用Log4Net的日志源名称
                    Timestamp = DateTime.Now
                };
                LogEntries.Add(logEntry);
            });
        }
    }

    // 对外暴露的快捷方法,和Log4Net用法保持一致
    public static void Info(string message, string source = null)
    {
        Log(Level.Info, message, source);
    }

    public static void Info(string message, Exception ex, string source = null)
    {
        Log(Level.Info, message, source, ex);
    }

    public static void Debug(string message, string source = null)
    {
        Log(Level.Debug, message, source);
    }

    public static void Warn(string message, string source = null)
    {
        Log(Level.Warn, message, source);
    }

    public static void Error(string message, string source = null)
    {
        Log(Level.Error, message, source);
    }

    public static void Error(string message, Exception ex, string source = null)
    {
        Log(Level.Error, message, source, ex);
    }

    public static void Fatal(string message, string source = null)
    {
        Log(Level.Fatal, message, source);
    }
}

使用示例

现在你只需要替换原来的log.Info("My message"),改成调用助手类的方法即可:

// 普通信息日志
LogHelper.Info("用户登录成功");

// 带自定义日志源的日志
LogHelper.Info("加载配置文件完成", "AppConfigService");

// 记录异常日志
try
{
    // 你的业务代码
}
catch (Exception ex)
{
    LogHelper.Error("加载数据失败", ex, "DataService");
}

关键注意点

  1. Log4Net配置:确保你的项目已经正确配置了Log4Net(比如App.config/Web.config里的输出到txt文件的配置),助手类里的_log实例才能正常工作。
  2. UI线程安全:用Application.Current.Dispatcher.Invoke确保ObservableCollection的修改在UI线程执行,避免绑定UI时出现跨线程异常。
  3. 集合初始化:如果LogEntries在App启动时还没初始化,记得在App.xaml.cs的OnStartup方法里提前初始化:LogHelper.LogEntries = new ObservableCollection<LogEntry>();

内容的提问来源于stack exchange,提问作者user979033

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:44:32