Skip to main content
 首页 » 编程设计

c#之运行 Asp.Net Core 2 的 Webapi 2 上带有 Serilog 的 DI ILogger

2024年02月25日33kevingrace

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

我已经添加了 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) 应该包括日志记录?

但是,当我将 ILogger DI 到我的 Controller 时;

[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: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'WebApi.Controllers.TraderContactController'.

我是否需要在 Startup.cs 中为 ILogger 物理设置单例。谁能告诉我我在这里缺少什么?正如我所假设的那样,因为日志记录是构建到核心管道中的,所以它知道如何解决这个问题?

请您参考如下方法:

您需要重构 Controller 以期待通用记录器 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; 
    } 
} 

ILogger<>映射到 Logger<>什么时候 .AddLogging() 在 CreateDefaultBuilder 内调用. ILogger没有直接在服务集合中注册。

完成后,将 Controller 耦合到实现问题(即 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 
} 

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

[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; 
    } 
 
    //... 
} 

所有涉及的类都将在解析时显式注入(inject)它们的依赖项。

这个答案假设 ITraderService和 TraderService已注册到 DI 容器。