如何独立封装Serilog配置并复用?当前类内重复配置是否合理?
问题解答
1. 你当前的做法是错误的
Log.Logger是Serilog的全局单例Logger实例,在每个类里重复执行new LoggerConfiguration().CreateLogger()并赋值给它,会每次覆盖之前的全局Logger,这既无意义,还可能导致日志行为不一致、资源浪费的问题。每个类只需要获取对应上下文的Logger,不需要重复初始化全局配置。
2. 可以将Serilog配置封装到单独类,无需通过继承复用
Serilog的配置只需要全局初始化一次,通常放在应用启动入口(比如Program.cs、Startup.cs)或专门的配置类中,完全不需要用继承来复用逻辑。你可以封装一个静态配置类统一管理初始化:
public static class SerilogConfig { public static void Initialize() { Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() .WriteTo.Console(outputTemplate: "{Timestamp:dd-MM-yyyy HH:mm:ss.fff zzz} " + "[{Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}") .CreateLogger(); } }
然后在应用启动时调用一次即可:
// 示例:在Program.cs的Main方法开头 SerilogConfig.Initialize();
3. 类中获取Logger的正确方式:使用Log.ForContext<T>
全局配置完成后,每个类只需通过Log.ForContext<T>()获取以当前类为SourceContext的Logger实例,这样日志里会显示对应的类名,方便定位问题。如果想减少重复代码,有两种方案:
方案一:直接在类中声明
public class Control { private readonly ILogger _log = Log.ForContext<Control>(); // 使用示例 public void DoSomething() { _log.Information("执行了DoSomething方法"); } }
方案二:通过泛型基类复用(可选)
如果觉得每个类都写Log.ForContext<T>麻烦,可以创建泛型基类,但要注意C#单继承的限制:
public abstract class BaseLoggable<T> where T : class { protected readonly ILogger _log = Log.ForContext<T>(); } // 子类直接继承使用 public class Control : BaseLoggable<Control> { public void DoSomething() { _log.Information("执行了DoSomething方法"); } }
总结
- 全局Logger配置只需初始化一次,禁止在每个类中重复配置
Log.Logger - 用单独静态类封装配置逻辑,在应用启动时调用一次即可
- 类中通过
Log.ForContext<T>获取对应上下文的Logger,泛型基类是可选的简化方案
内容的提问来源于stack exchange,提问作者bodrovdeni
相关产品推荐
相关产品推荐

