建立一个虚拟公司的网站,做汽车微信广告视频网站有哪些,哈尔滨市工程建设信息网,滨江区高端网站建设优化 .NET Core logging 中的泛型 loggerIntro在微软的 logging 组件中#xff0c;我们可以比较方便的使用泛型 Logger#xff0c;如#xff1a;ILoggerGeneric 这样的#xff0c;但是如果泛型 Logger 的类型是一个泛型类型就会有些问题#xff0c;具体的泛型参数… 优化 .NET Core logging 中的泛型 loggerIntro在微软的 logging 组件中我们可以比较方便的使用泛型 Logger如ILoggerGeneric 这样的但是如果泛型 Logger 的类型是一个泛型类型就会有些问题具体的泛型参数不会作为 categoryName 的一部分我们可以实现一个自己的 ILoggerT 来改变这个行为详细可以参考下面的介绍Reproduce这个问题非常好重现只需要一个测试的泛型类就可以了我写了一个简单的测试类定义如下private class GenericTestT
{private readonly ILoggerGenericTestT _logger;public GenericTest(ILoggerGenericTestT logger){_logger logger;}public void Test() _logger.LogInformation(test);
}
测试代码如下using var services new ServiceCollection().AddLogging(builder builder.AddConsole()).AddSingleton(typeof(GenericTest)).BuildServiceProvider();
services.GetRequiredServiceGenericTestint().Test();
services.GetRequiredServiceGenericTeststring().Test();
这里使用了两个泛型类型一个泛型参数是 int一个是 string来看上面代码的输出结果吧输出结果如下可以看到默认的日志行为我们没有办法区分泛型类的泛型参数具体是什么这对于我们来说有时候是很不方便的Whats inside我们可以在 Github 上找到 logging 组件的源代码可以参考https://github.com/dotnet/runtime/blob/fa06656c41947e22fc6efd909cce0a6a180f1078/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LoggerT.cs通过源码我们可以看到默认的行为并不会记录泛型参数经过测试如果我们需要包含泛型参数信息只需要把 includeGenericParameters 参数设置为 true 即可既然明确了如何实现我们期望的效果改起来就会很简单Cutom Generic Logger微软的 Logging 非常的依赖注入泛型的 Logger 也是依赖注入的我们只需要注入自己的泛型 Logger 实现就可以代替默认的行为了可以参考https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Logging/src/LoggingServiceCollectionExtensions.cs#L42为了不造成 breaking change我们可以加一个配置默认还是与微软现在的行为保持一致针对想要区分的类型使用带泛型参数的行为实现代码如下// 泛型 logger 配置
public sealed class GenericLoggerOptions
{// 返回 true 则使用带泛型参数的 typeName否则使用默认的行为public FuncType, bool? FullNamePredict { get; set; }
}internal sealed class GenericLoggerT : ILoggerT
{private readonly ILogger _logger;/// summary/// Creates a new see crefGenericLogger{T}/./// /summary/// param namefactoryThe factory./param/// param nameoptionsGenericLoggerOptions/parampublic GenericLogger(ILoggerFactory factory, IOptionsGenericLoggerOptions options){if (factory null){throw new ArgumentNullException(nameof(factory));}// 通过配置的委托来判断是否要包含泛型参数var includeGenericParameters options.Value.FullNamePredict?.Invoke(typeof(T)) true;_logger factory.CreateLogger(TypeHelper.GetTypeDisplayName(typeof(T), includeGenericParameters: includeGenericParameters, nestedTypeDelimiter: .));}/// inheritdoc /IDisposable ILogger.BeginScopeTState(TState state){return _logger.BeginScope(state);}/// inheritdoc /bool ILogger.IsEnabled(LogLevel logLevel){return _logger.IsEnabled(logLevel);}/// inheritdoc /void ILogger.LogTState(LogLevel logLevel, EventId eventId, TState state, Exception? exception, FuncTState, Exception?, string formatter){_logger.Log(logLevel, eventId, state, exception, formatter);}public void LogTState(LogLevel logLevel, EventId eventId, TState state, Exception exception, FuncTState, Exception, string formatter) throw new NotImplementedException();public bool IsEnabled(LogLevel logLevel) throw new NotImplementedException();public IDisposable BeginScopeTState(TState state) throw new NotImplementedException();
}
TypeHelper 中的方法就是微软 Logging 中引用的 TypeNameHelper因为是 internal所以单独拷出来一份上面的 Logger 与微软默认的 logger 唯一的不同之处就在于多了一个配置。。为了使用起来方便定义了一个 ILoggingBuilder 的扩展方法定义如下public static ILoggingBuilder UseCustomGenericLogger(this ILoggingBuilder loggingBuilder, ActionGenericLoggerOptions genericLoggerConfig)
{Guard.NotNull(loggingBuilder, nameof(loggingBuilder));Guard.NotNull(genericLoggerConfig, nameof(genericLoggerConfig));loggingBuilder.Services.Configure(genericLoggerConfig);loggingBuilder.Services.AddSingleton(typeof(ILogger), typeof(GenericLogger));return loggingBuilder;
}
好了现在我们来测试一下我们自己的泛型 logger 吧测试代码如下using var services new ServiceCollection().AddLogging(builder builder.AddConsole().UseCustomGenericLogger(options options.FullNamePredict _ true)).AddSingleton(typeof(GenericTest)).BuildServiceProvider();
services.GetRequiredServiceGenericTestint().Test();
services.GetRequiredServiceGenericTeststring().Test();
输出结果如下可以看到现在的输出日志中已经包含了泛型类型的泛型参数如果你对自己名称还不够满意也可以自定义 GetTypeDisplayName 的行为More上面的测试代码有需要的可以从 Github 上获取https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/DotNetCoreSample/LoggerTest.cs#L37感觉泛型参数还是记录一下的比较好这样我们才能知道具体是哪一个类型打印出来的日志像第一种方式打印出来的日志完全就是一脸懵逼真正出现了问题完全不知道是哪一个类型的日志只能靠猜了这体验就太不好了不过还好我们可以比较方便的进行定制。不知道你是否也有这样的想法呢在 Github 上提了一个 issue https://github.com/dotnet/runtime/issues/51368如果感兴趣可以关注一下 留下你的看法Referenceshttps://github.com/dotnet/runtime/issues/51368https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/DotNetCoreSample/LoggerTest.cs#L37