我为Asp.Net Core 2.0配置了Serilog,它在我的启动web项目中通过.Net Core依赖注入工作得很好(如果我通过Microsoft.Extensions.Logging使用它),但我无法从任何其他项目访问它 .
这就是我所拥有的:
Program.cs
using System;
using System.IO;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Serilog;
namespace ObApp.Web.Mvc
{
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.Build();
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.CreateLogger();
try
{
Log.Warning("Starting BuildWebHost");
BuildWebHost(args).Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog()
.Build();
}
}
Startup.cs
启动.cs是纯默认的 . 我没有从新的Asp.Net Core MVC项目的原始模板中以任何方式改变它 .
我原以为我可能需要在IServiceCollection服务中添加Serilog,但是文章Leaner,更简单的ASP.NET Core 2登录https://nblumhardt.com/2017/08/use-serilog/告诉我这是不必要的 .
然后您可以继续删除任何其他 Logger 配置:appsettings.json中不需要“Logging”部分,任何地方都不需要AddLogging(),也不需要通过Startup.cs中的ILoggerFactory进行配置 . UseSerilog()取代内置的ILoggerFactory,以便应用程序中的每个 Logger ,无论是Serilog的Log类,Serilog的ILogger还是Microsoft.Extensions.Logging.ILogger,都将使用相同的Serilog实现进行备份,并通过相同的配置进行控制 .
What I Expected
能够在解决方案的任何项目中的任何类中通过构造函数简单地注入 Logger . 例如:
using Serilog;
public MyTestClass(ILogger logger) { ... }
What I Got - Web (Startup) Project
如果我使用Microsoft.Extensions.Logging包装器,注入在HomeController中工作:
using Microsoft.Extensions.Logging;
public class HomeController : Controller
{
ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
_logger.LogDebug("Controller instantiated.");
}
}
如果我尝试注入Serilog.ILogger,则在任何项目/类中注入失败
using Serilog;
using Serilog.Extensions.Logging; // Not sure if this would help.
public class HomeController : Controller
{
ILogger _logger;
public HomeController(ILogger logger)
{
_logger = logger;
_logger.Debug("Controller instantiated.");
}
}
InvalidOperationException:尝试激活'ObApp2.Web.Mvc.Controllers.HomeController'时,无法解析类型'Serilog.ILogger'的服务 .
My Bigger Issue - OtherProjects
我更大的问题是,如果我在解决方案中的另一个项目中工作,我无法通过我尝试过的任何方法获取 Logger .
当我尝试使用Microsoft.Extensions.Logging或使用Serilog注入时,我在构建时遇到缺少的参数异常 .
using Microsoft.Extensions.Logging;
namespace ObApp.Domain
{
public class MyTestClass(ILogger<MyTestClass> logger) { ... }
- or -
using Serilog;
namespace ObApp.Domain
{
public class MyTestClass(ILogger logger) { ... }
两者都生成类似于的构建错误:
没有任何参数对应于'MyTestClass.MyTestClass(ILogger)'所需的形式参数'logger'
Questions
-
当注入这种类型的Serilog配置时,是否建议我在我正在进行注入的类文件中引用Microsoft.Extensions.Logging或Serilog?
-
如何让DI在所有项目中运作?
2 回答
此解决方案正确地将 Logger 注入外部项目或库中的类 .
我也尝试过Rufus提出的答案 . 我没有OP描述的问题,但我有一个更奇怪的问题:在
ILogger
注入外部项目后,登录到MS SQL停止工作 . 控制台记录工作 . 由于Serilog主要是静态服务,我意识到我应该将Log.Logger
视为工厂 . 好处是您仍然可以自定义ILogger
引用(例如,在构造函数中添加ForContext
)而不会影响"singleton"服务 .我在github上发布了一个完整的工作解决方案,包括一个设置DI的控制台程序(将从ASP.NET Core中运行相同),一个包含Serilog入门的零除演示的外部库,以及另一个库管理Serilog作为服务 .
重要的部分,Serilog服务注册,看起来像这样(作为奖励,我们绑定到
ProcessExit
进行透明清理):一种对我有用的方法:
我使用ConfigureServices方法中的AddSingleton()方法添加了一个Serilog.Core.Logger实例 . 这解决了DI问题 . 此步骤将替换在StartUp构造函数中将Logger实例分配给Log.Logger的步骤 .
还要更改类文件中的引用以指向Serilog.Ilogger