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

.NET日志简单包装器(适配Serilog/NLog)完整工作示例求助

.NET 日志包装器完整实现(适配器模式)

我给你整理了一个直接可运行的日志包装器方案,用适配器模式把Serilog、NLog这些第三方日志框架适配到统一的抽象接口上,业务代码完全不用关心底层用的是哪个日志库,后续切换或者新增框架也非常方便。

1. 定义统一的日志抽象接口

首先我们先定义一个通用的ILogger接口,包含常用的日志级别方法:

public interface ILogger
{
    void Debug(string message, params object[] args);
    void Info(string message, params object[] args);
    void Warn(string message, params object[] args);
    void Error(string message, params object[] args);
    void Error(Exception ex, string message, params object[] args);
    void Fatal(string message, params object[] args);
    void Fatal(Exception ex, string message, params object[] args);
}

2. 适配器基类(可选,减少重复代码)

为了避免每个适配器都重复实现接口方法,我们可以写一个抽象基类:

public abstract class LoggerAdapterBase : ILogger
{
    public abstract void Debug(string message, params object[] args);
    public abstract void Info(string message, params object[] args);
    public abstract void Warn(string message, params object[] args);
    public abstract void Error(string message, params object[] args);
    public abstract void Error(Exception ex, string message, params object[] args);
    public abstract void Fatal(string message, params object[] args);
    public abstract void Fatal(Exception ex, string message, params object[] args);
}

3. 实现Serilog适配器

这个适配器把我们的ILogger接口方法映射到Serilog的日志方法:

using Serilog;

public class SerilogLoggerAdapter : LoggerAdapterBase
{
    private readonly Serilog.ILogger _logger;

    // 支持传入自定义Serilog实例,默认用全局Log.Logger
    public SerilogLoggerAdapter(Serilog.ILogger logger = null)
    {
        _logger = logger ?? Log.Logger;
    }

    public override void Debug(string message, params object[] args) => _logger.Debug(message, args);
    public override void Info(string message, params object[] args) => _logger.Information(message, args);
    public override void Warn(string message, params object[] args) => _logger.Warning(message, args);
    public override void Error(string message, params object[] args) => _logger.Error(message, args);
    public override void Error(Exception ex, string message, params object[] args) => _logger.Error(ex, message, args);
    public override void Fatal(string message, params object[] args) => _logger.Fatal(message, args);
    public override void Fatal(Exception ex, string message, params object[] args) => _logger.Fatal(ex, message, args);
}

4. 实现NLog适配器

同理,写NLog的适配器:

using NLog;

public class NLogLoggerAdapter : LoggerAdapterBase
{
    private readonly NLog.ILogger _logger;

    // 支持传入自定义NLog实例,默认用当前类的日志实例
    public NLogLoggerAdapter(NLog.ILogger logger = null)
    {
        _logger = logger ?? LogManager.GetCurrentClassLogger();
    }

    public override void Debug(string message, params object[] args) => _logger.Debug(message, args);
    public override void Info(string message, params object[] args) => _logger.Info(message, args);
    public override void Warn(string message, params object[] args) => _logger.Warn(message, args);
    public override void Error(string message, params object[] args) => _logger.Error(message, args);
    public override void Error(Exception ex, string message, params object[] args) => _logger.Error(ex, message, args);
    public override void Fatal(string message, params object[] args) => _logger.Fatal(message, args);
    public override void Fatal(Exception ex, string message, params object[] args) => _logger.Fatal(ex, message, args);
}

5. 日志包装器(可选,统一处理逻辑)

如果需要给所有日志加统一前缀、过滤或者其他全局处理,可以写一个包装器类:

public class LogWrapper : ILogger
{
    private readonly ILogger _logger;

    // 注入具体的适配器实例
    public LogWrapper(ILogger logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    // 示例:给所有日志添加应用前缀
    private string FormatMessage(string message)
    {
        return $"[MyApplication] {message}";
    }

    public void Debug(string message, params object[] args) => _logger.Debug(FormatMessage(message), args);
    public void Info(string message, params object[] args) => _logger.Info(FormatMessage(message), args);
    public void Warn(string message, params object[] args) => _logger.Warn(FormatMessage(message), args);
    public void Error(string message, params object[] args) => _logger.Error(FormatMessage(message), args);
    public void Error(Exception ex, string message, params object[] args) => _logger.Error(ex, FormatMessage(message), args);
    public void Fatal(string message, params object[] args) => _logger.Fatal(FormatMessage(message), args);
    public void Fatal(Exception ex, string message, params object[] args) => _logger.Fatal(ex, FormatMessage(message), args);
}

6. 完整使用示例

首先安装对应的NuGet包:

  • 对于Serilog:Install-Package Serilog 和 Install-Package Serilog.Sinks.Console
  • 对于NLog:Install-Package NLog 和 Install-Package NLog.Config

然后在Program.cs里测试:

using System;

class Program
{
    static void Main(string[] args)
    {
        // 测试Serilog
        Console.WriteLine("=== 使用Serilog日志 ===");
        ConfigureSerilog();
        var serilogAdapter = new SerilogLoggerAdapter();
        var logger = new LogWrapper(serilogAdapter);
        TestLogger(logger);

        Console.WriteLine("\n=== 切换到NLog日志 ===");
        // 测试NLog
        ConfigureNLog();
        var nlogAdapter = new NLogLoggerAdapter();
        logger = new LogWrapper(nlogAdapter);
        TestLogger(logger);
    }

    // 配置Serilog
    private static void ConfigureSerilog()
    {
        Serilog.Log.Logger = new Serilog.LoggerConfiguration()
            .MinimumLevel.Debug()
            .WriteTo.Console()
            .CreateLogger();
    }

    // 配置NLog(也可以用NLog.config文件)
    private static void ConfigureNLog()
    {
        var config = new NLog.Config.LoggingConfiguration();
        var consoleTarget = new NLog.Targets.ConsoleTarget("console")
        {
            Layout = "${date:format=HH:mm:ss} ${level} ${message}"
        };
        config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, consoleTarget);
        NLog.LogManager.Configuration = config;
    }

    // 测试日志方法
    private static void TestLogger(ILogger logger)
    {
        logger.Debug("这是一条Debug级别的日志");
        logger.Info("这是一条Info级别的日志");
        logger.Warn("这是一条Warn级别的日志");
        
        try
        {
            throw new InvalidOperationException("模拟业务异常");
        }
        catch (Exception ex)
        {
            logger.Error(ex, "执行操作时发生错误");
        }
        
        logger.Fatal("这是一条Fatal级别的日志");
    }
}

方案优势

  • 解耦业务与日志框架:业务代码只依赖ILogger接口,完全不用关心底层用的是Serilog还是NLog
  • 扩展性强:新增其他日志框架(比如log4net)只需要写对应的适配器类,不用修改任何业务代码
  • 统一处理逻辑:通过LogWrapper可以轻松添加全局日志处理,比如前缀、上下文信息、日志过滤等

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:43:07