DI ILogger with Serilog on Webapi 2 running Asp.Net Core 2



我正在尝试将Serilog集成到我的WebApi 2中 Asp.Net Core 2(使用MSSQLServer集成)。

我已经添加了 nuget 包,然后将以下内容添加到我的

public async void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

var log = new LoggerConfiguration()
.WriteTo.MSSqlServer(DbGlobals.DevDatabase, "Logs")
.CreateLogger();
loggerFactory.AddSerilog(log);

在我的Program.cs中,我有默认值;

public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();

通过阅读 MSDN 文档.CreateDefaultBuilder(args)应该包括日志记录?

但是,当我随后将ILoggerDI到我的控制器时;

[Route("api/[controller]")]
public class TraderController : Controller
{
private TraderService _service;
private readonly ILogger _logger;
public TraderController(Func<IBemfeitoDataContext> context, ILogger logger)
{
_service = new TraderService(context, logger);
_logger = logger;
}

我收到以下错误;

InvalidOperationException:尝试激活"WebApi.Controllers.TraderContactController"时,无法解析类型"Microsoft.Extensions.Logging.ILogger"的服务。

我是否需要在启动.cs中为ILogger物理设置单例。谁能告诉我我在这里错过了什么?正如我所假设的那样,因为日志记录内置于 Core 管道中,这将是它知道如何解决的问题?

您需要重构控制器以期望通用记录器ILogger<T>,它派生自ILogger

[Route("api/[controller]")]
public class TraderController : Controller {
private TraderService _service;
private readonly ILogger _logger;
public TraderController(
Func<IBemfeitoDataContext> context, 
ILogger<TraderController> logger //<-- note the change here
) { 
_service = new TraderService(context, logger);
_logger = logger;
}
}

当在CreateDefaultBuilder中调用.AddLogging()时,ILogger<>映射到Logger<>ILogger不会直接向服务集合注册。

完成此操作后,当前将控制器耦合到实现问题(即TraderService)的设计选择引起了一些关注。

假设基于当前代码的使用方式

public class TraderService : ITraderService {
private readonly ILogger logger;
public TraderService(Func<IBemfeitoDataContext> context, ILogger logger) {
this.logger = logger;
//...
}
//...code removed for brevity
}

该服务也应固定为依赖于ILogger<T>

public class TraderService : ITraderService {
private readonly ILogger logger;
public TraderService(Func<IBemfeitoDataContext> context, ILogger<TraderService> logger) {
this.logger = logger;
//...
}
//...code removed for brevity
}

并且应该重构控制器以依赖于服务抽象而不是实现。

[Route("api/[controller]")]
public class TraderController : Controller {
private readonly ITraderService service;
private readonly ILogger logger;
public TraderController(ITraderService service, ILogger<TraderController> logger) { 
this.service = service;
this.logger = logger;
}
//...
}

所有涉及的类在解析时都将显式注入其依赖项。

此答案假定ITraderServiceTraderService已注册到 DI 容器。

注入ILoggerFactory和泛型ILogger<T>。这意味着你可以像这样拥有你的控制器:

[Route("api/[controller]")]
public class TraderController : Controller {
private readonly ITraderService service;
private readonly ILogger logger;
public TraderController(ITraderService service, ILoggerFactory loggerFactory) 
{ 
this.service = service;
this.logger = loggerFactory.CreateLogger<TraderController>();
}
//...
}

最新更新