我会尽量解释我的情况,我希望这是有意义的。
我的项目是一个 .NET 核心 Web API。使用一个单独的类库项目,其中包含包括我的 DbContext 内容在内的模型。
问题#1我希望能够从启动中登录到控制台.cs
原因:我目前正在调试从环境变量设置变量。我想输出已设置为控制台的内容。
示例:如何从启动中写入日志.cs
现在,解决方案是将 ILoggerFactory 添加到 Program 中的服务容器中.cs如下所示:
var host = new WebHostBuilder()
.UseKestrel()
.ConfigureServices(s => {
s.AddSingleton<IFormatter, LowercaseFormatter>();
})
.ConfigureLogging(f => f.AddConsole(LogLevel.Debug))
.UseStartup<Startup>()
.Build();
host.Run();
接下来,更改 Startup.cs 构造函数以接收将从我们刚刚注册的容器中获取的 ILoggerFactory。如下:
public class Startup {
ILogger _logger;
IFormatter _formatter;
public Startup(ILoggerFactory loggerFactory, IFormatter formatter){
_logger = loggerFactory.CreateLogger<Startup>();
_formatter = formatter;
}
public void ConfigureServices(IServiceCollection services) {
_logger.LogDebug($"Total Services Initially: {services.Count}");
// register services
//services.AddSingleton<IFoo, Foo>();
}
public void Configure(IApplicationBuilder app, IFormatter formatter) {
// note: can request IFormatter here as well as via constructor
_logger.LogDebug("Configure() started...");
app.Run(async (context) => await context.Response.WriteAsync(_formatter.Format("Hi!")));
_logger.LogDebug("Configure() complete.");
}
这解决了我的问题 - 我可以运行该应用程序,它现在可以正常工作,在我需要的地方记录。
然而。
然后当我尝试运行dotnet ef数据库更新时--startup-project=myAPIProject
它现在失败了,因为 EF 不通过 Program.cs,而是尝试直接实例化我的 Startup 类。而且由于现在我的构造函数需要一个 ILoggerFactory,EF 不知道该怎么做并抛出异常。
有谁知道解决这个问题的方法?
好的,所以我找到了一个解决方案。
而不是将 ILoggerFactory 传递给 Startup.cs 构造函数。按如下方式传递 ILogger:
private ILogger<Startup> _logger;
public Startup(IHostingEnvironment env, ILogger<Startup> logger) {
_env = env;
_logger = logger;
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
_configuration = builder.Build();
}
我的程序.cs如下所示:
var host = new WebHostBuilder()
.UseKestrel()
.UseConfiguration(config)
.ConfigureServices(s => s.AddSingleton<IConfigurationRoot>(config))
.ConfigureLogging(f => {
f.AddConsole()
.AddDebug();
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
这是因为我们的启动构造函数通过 DI 容器传递 ILogger(即使通过 EF 迁移运行并且我们尚未配置记录器(。
我在阅读后想通了这一点:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/startup(在"启动中可用的服务"下(。
现在。。。我在使用 .NET core 时遇到了很多令人沮丧的问题。我猜可能是因为它仍处于起步阶段,最佳实践等的文档仍在改进。因为我读过的大多数指南都没有这样做。
我觉得这也部分是因为 .NET core 中向"约定重于配置"的转变 - 这显然有缺点。使用强类型语言(如 C#(的好处在于,你可以让编译器在运行时之前帮助你识别此类问题。
(请记住,ILoggerFactory 一切正常,直到您使用无法访问 Program.cs 中添加服务的 EF 运行迁移(
渴望听到人们对此的看法。我相信其他人一定也经历过同样的挫折。不要误会我的意思,我喜欢 .NET core,但是在这个应用程序的开发过程中,有很多次我被困在像这样最简单的愚蠢问题上几个小时(有时更长(,这些问题本可以花在编写代码上。