我正在尝试使用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
转到我的控制器时;
[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:无法解析类型&#39; Microsoft.Extensions.Logging.ILogger&#39;的服务。尝试激活WebApi.Controllers.TraderContactController&#39;。
我是否需要在Startup.cs中为ILogger
物理设置单例。谁能告诉我这里缺少什么?正如我所假设的那样,因为日志记录已构建到Core管道中,这将是它知道如何解决的问题吗?
答案 0 :(得分:2)
您需要重构控制器以期望通用记录器 if item_formset.is_valid() == False:
return self.render_to_response(self.get_context_data(form=form,item_formset=item_formset ))
subTotal=0
i=0
for f in item_formset.forms:
subTotal += float(f.data['item-'+str(i)+'-total'])
i=i+1
if subTotal!= float(form.data['total']):
form.add_error('total', "Total is incorrect.")
return self.render_to_response(self.get_context_data(form=form,item_formset=item_formset ))
,它来自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;
}
}
内调用.AddLogging()
时, ILogger<>
会映射到Logger<>
。 CreateDefaultBuilder
未直接在服务集合中注册。
完成这项工作后,将控制器与实现问题(即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
}
所有涉及的类将在解析时显式注入其依赖项。
此答案假定{DI封容器中已注册[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;
}
//...
}
和ITraderService
。
答案 1 :(得分:1)
同时注入了 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>();
}
//...
}