Bjo*_*pen 13 asp.net logging asp.net-core
ASP.NET Core内置了对日志记录的支持,但是文档指出应该通过请求ILogger
via依赖注入来完成日志记录,即将它作为参数添加到Controller
构造函数中.
我的代码中带有ILogger
参数的污染方法签名或构造函数对于这种跨领域的关注感觉就像是错误的解决方案.在Android中,Log
类是静态的,使得从代码的任何部分进行日志记录变得微不足道.
从控制器以外的其他地方进行日志记录的好方法是什么?
Set*_*Set 16
关于在任何组件中使用日志:
通过请求a
ILoggerFactory
或ILogger<T>
via依赖注入来向应用程序中的组件添加日志记录.如果ILoggerFactory
请求了,则必须使用其CreateLogger
方法创建记录器.
如果您CustomClass
是一个数据容器(DTO类),它不应该知道日志记录,而只是包含数据.
对于名称如"Service","Provider","Handler"等的其他类,最佳实践是使用依赖注入来解析实例.通常,您应该在任何可能的地方使用DI,因为这是一种在对象及其协作者或依赖关系之间实现松散耦合的技术.有关更多信息,以下问题可能很有趣:我应该使用依赖注入还是静态工厂?
因此,只需添加ILogger<CustomClass>
到其构造函数(实际上与控制器相同),因为.NET Core默认只支持构造函数注入:
public class CustomClass
{
private readonly ILogger _logger;
public CustomClass(ILogger<CustomClass> logger)
{
_logger = logger;
}
}
Run Code Online (Sandbox Code Playgroud)
ASP.NET Core的内置依赖注入容器将自动解决瞬态依赖关系.因此,如果您的控制器将类A
作为依赖项使用B
您想要记录某事的类,那么您的代码可能是这样的:
public class MyController
{
public MyController(ClassA classA)
{ ... }
}
public class ClassA
{
public ClassA(ClassB classB)
{ ... }
}
public class ClassB
{
private readonly ILogger _logger;
public ClassB(ILogger<ClassB> logger)
{
_logger = logger;
}
public void DoSomethingWithLogging()
{
// use _logger
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,您还需要Startup
使用IServiceCollection.Add…
方法注册依赖项:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddTransient<ClassB>();
services.AddTransient<ClassA>();
}
Run Code Online (Sandbox Code Playgroud)
内置日志记录支持意味着开箱即用的.NET Core知道并使用内置抽象进行日志记录.这主要由ILoggerFactory
和 ILoggerProvider
接口完成 .
/// <summary>
/// Represents a type used to configure the logging system and create instances of <see cref="ILogger"/> from
/// the registered <see cref="ILoggerProvider"/>s.
/// </summary>
public interface ILoggerFactory : IDisposable
// <summary>
/// Represents a type that can create instances of <see cref="ILogger"/>.
/// </summary>
public interface ILoggerProvider : IDisposable
Run Code Online (Sandbox Code Playgroud)
使用您自己的ILoggerProvider
实现,您可以添加自己的记录器,可以做任何你想做的事情.您可以将NLog记录器实现作为工作示例进行检查.
多亏了ILoggerFactory
,您可以根据项目特定目的配置Logger:
要在ASP.NET Core应用程序中配置日志记录,您应该
ILoggerFactory
在类的Configure
方法中解析Startup
.ILoggerFactory
当您向该Configure
方法添加此类型的参数时,ASP.NET Core将自动提供使用依赖注入的实例.
分享 Bjorn Reppens 对已接受答案的担忧,并考虑到 Cyprien Autexiers 的评论,我最终得到了“内置 DI”的这个(简化)解决方案,而在 .NET Core 的“控制器以外的其他类”中没有“污染构造函数” 3.1
工厂:
public class Runtime
{
public static ILogger<T> GetLogger<T>()
{
using var serviceScope = host.Services.CreateScope();
var services = serviceScope.ServiceProvider;
return services.GetRequiredService<ILogger<T>>();
}
static IHost host;
CancellationTokenSource CancellationSource { get; } = new CancellationTokenSource();
Task hostTask;
public void Start()
{
var hostBuilder = Host.CreateDefaultBuilder();
hostBuilder.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
host = hostBuilder.Build();
hostTask = host.RunAsync(CancellationSource.Token);
}
}
Run Code Online (Sandbox Code Playgroud)
客户:
public class OtherClass
{
ILogger Logger { get; }
public OtherClass() => Logger = Runtime.GetLogger<OtherClass>();
}
Run Code Online (Sandbox Code Playgroud)
进一步抽象:
public abstract class LoggerBase<T>
{
protected ILogger Logger => RunTime.GetLogger<T>();
}
Run Code Online (Sandbox Code Playgroud)
例如
public class OtherClass : LoggerBase<OtherClass>
{
public OtherClass() => Logger.LogInformation("Instantiated");
}
Run Code Online (Sandbox Code Playgroud)
本文指出您应该使用DI在所有需要它的类中注入您的记录器:https: //docs.asp.net/en/latest/fundamentals/logging.html
"这种技术不仅限于控制器,也可以由任何使用依赖注入的应用程序服务使用."
另一方面,这篇文章(微软赞助)提到了一种全局静态参考方法:https: //msdn.microsoft.com/en-us/magazine/mt694089.aspx?f = 255&MSPPError = -2147217396
"正如您可能注意到的,这需要访问先前配置了提供程序的同一个记录器工厂实例.虽然可以想象您可以将记录器工厂实例传递到您要执行日志记录的每个类,但它很快就会成为那会讨厌重构的麻烦.
解决方案是将单个静态ILoggerFactory保存为静态属性,在实例化其对象的特定ILoggger实例时可用于所有类.例如,考虑添加一个包含静态ILoggerFactory实例的ApplicationLogging静态类:"
我没有尝试使用静态与DI对比服务定位器:模式或反模式辩论,我个人发现常见的跨领域问题,如日志记录和配置,以适应后一种方法,但过去曾使用过这两种方法.
归档时间: |
|
查看次数: |
8756 次 |
最近记录: |