.NET 6中如何将Serilog自定义属性日志代码简化为单行?
简化Serilog日志自定义属性的单行写法(.NET 6.0)
针对你提到的using块导致日志代码繁琐的问题,以下是几种在.NET 6.0中实现单行日志+自定义属性的可行方案:
方案1:给ILogger编写扩展方法(推荐)
这是侵入性最低的方案,无需修改现有依赖注入逻辑,直接扩展原生ILogger的功能:
单属性扩展
public static class LoggerPropertyExtensions { public static void LogInformationWithProperty(this ILogger logger, string propertyName, object propertyValue, string message, params object[] args) { using (logger.BeginScope(new Dictionary<string, object> { { propertyName, propertyValue } })) { logger.LogInformation(message, args); } } // 同理可扩展LogWarning、LogError等其他级别 public static void LogErrorWithProperty(this ILogger logger, string propertyName, object propertyValue, string message, params object[] args) { using (logger.BeginScope(new Dictionary<string, object> { { propertyName, propertyValue } })) { logger.LogError(message, args); } } }
调用示例(直接单行完成):
_logger.LogInformationWithProperty("MyVar", var, "My logging message...");
多属性重载
如果需要一次性添加多个自定义属性,可以扩展多参数版本:
public static void LogInformationWithProperties(this ILogger logger, IDictionary<string, object> properties, string message, params object[] args) { using (logger.BeginScope(properties)) { logger.LogInformation(message, args); } }
调用示例:
var props = new Dictionary<string, object> { { "MyVar", var }, { "UserId", userId } }; _logger.LogInformationWithProperties(props, "My logging message...");
如果偏好使用Serilog的LogContext,也可以写对应的扩展:
public static void LogInformationWithSerilogProperty(this ILogger logger, string propertyName, object propertyValue, string message, params object[] args) { using (LogContext.PushProperty(propertyName, propertyValue)) { logger.LogInformation(message, args); } }
注意:使用
LogContext时,必须在Serilog配置中开启Enrich.FromLogContext(),否则自定义属性不会被输出到日志。
方案2:自定义日志包装类
如果需要统一管理所有日志逻辑(比如全局默认属性、多环境适配),可以封装一个自定义日志类:
public class AppLogger<T> { private readonly ILogger<T> _innerLogger; public AppLogger(ILogger<T> innerLogger) { _innerLogger = innerLogger; } public void LogInfo(string propertyName, object propertyValue, string message, params object[] args) { using (_innerLogger.BeginScope(new Dictionary<string, object> { { propertyName, propertyValue } })) { _innerLogger.LogInformation(message, args); } } // 其他日志级别方法按需实现 }
在DI容器中注册:
// .NET 6 Program.cs中 builder.Services.AddScoped(typeof(AppLogger<>), typeof(AppLogger<>));
调用示例:
// 注入AppLogger<T> private readonly AppLogger<MyService> _appLogger; public MyService(AppLogger<MyService> appLogger) { _appLogger = appLogger; } // 单行调用 _appLogger.LogInfo("MyVar", var, "My logging message...");
关于ILoggerFactory的说明
ILoggerFactory主要用于创建和配置ILogger实例,无法直接实现单次日志的自定义属性注入。但你可以通过它配置Serilog的全局Enricher,添加所有日志都包含的公共属性(如应用版本、环境名),但这不适用于你需要的单次动态属性场景。
内容的提问来源于stack exchange,提问作者Scottish Smile
相关产品推荐
相关产品推荐

