繁体   English   中英

运行Asp.Net Core 2的Webapi 2上带有Seri​​log的DI ILogger

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

我正在尝试使用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到控制器时;

[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”的服务。

我是否需要在Startup.cs中为ILogger物理设置单例。 谁能告诉我我在这里想念的吗? 正如我假设的那样,因为日志记录已内置到Core管道中,所以它知道如何解决该问题?

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM