C# 将Asp.NETCore2注入用于多个项目的Serilog
我为Asp.Net Core 2.0配置了Serilog,它通过启动web项目中的.Net Core依赖项注入(如果我通过Microsoft.Extensions.Logging使用它)工作得很好,但我无法从任何其他项目访问它 以下是我所拥有的: Program.csC# 将Asp.NETCore2注入用于多个项目的Serilog,c#,asp.net,logging,asp.net-core-mvc,serilog,C#,Asp.net,Logging,Asp.net Core Mvc,Serilog,我为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.Exte
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();
}
}
我得到了什么-网络(创业)项目
如果使用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.");
}
}
InvalidOperationException:无法解析服务
尝试激活时输入'Serilog.ILogger'
'ObApp2.Web.Mvc.Controllers.HomeController'
我的大问题-其他项目
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();
}
}
我更大的问题是,如果我在解决方案中的另一个项目中工作,我无法通过我尝试过的任何方法通过DI获得记录器
当我尝试使用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) { ... }
使用Microsoft.Extensions.Logging;
命名空间ObApp.Domain
{
公共类MyTestClass(ILogger记录器){…}
-或-
使用Serilog;
命名空间ObApp.Domain
{
公共类MyTestClass(ILogger记录器){…}
两者都会生成生成错误,类似于:
没有给出与所需的形式化参数相对应的参数
“MyTestClass.MyTestClass(ILogger)”的参数“logger”
问题
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();
}
}
有一种方法对我有效: 我在ConfigureServices方法中使用AddSingleton()方法添加了Serilog.Core.Logger的实例。这解决了DI问题。此步骤取代了在启动构造函数中将Logger实例分配给Log.Logger的步骤
services.AddSingleton((ILogger)new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.File(<...>)
.CreateLogger());
services.AddSingleton((ILogger)new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.File()文件
.CreateLogger());
还要更改类文件中的引用以指向Serilog.Ilogger此解决方案正确地将记录器注入到外部项目或库中的类中 我也尝试了Rufus建议的答案。我没有OP描述的问题,但我有一个更奇怪的问题:在
ILogger
被注入外部项目后,MS SQL的日志记录停止了工作。控制台日志记录工作。由于Serilog主要是一个静态服务,我意识到我应该将Log.Logger
视为工厂。好处是您仍然可以自定义ILogger
引用(例如,在构造函数中添加ForContext
),而不会影响“singleton”服务
我已经发布了一个完整的工作解决方案,包括一个设置DI的控制台程序(在ASP.NET Core中也可以使用),一个包含Serilog getting started by zero demo的外部库,以及另一个作为服务管理Serilog的库
重要的部分,Serilog服务注册,看起来是这样的(作为奖励,我们将ProcessExit
绑定到透明清理):
您不能通过NetCore中的DI访问Serilog。它是静态的。 在程序.Main()中正确配置和初始化记录器后,只需像启动、控制器等中的任何其他静态程序一样访问即可
public void ConfigureServices(IServiceCollection services)
{
Serilog.Log.Information("here I am in startup");
//further options
};
或在顶部添加:
使用静态Serilog.Log;
简单地说:
信息(“击键保存”);
事实上,我一直在努力使用相同的设置,但我成功地使其工作。解决方案在以下方面与您的代码示例略有不同:
- 它取决于
Microsoft.Extensions.Logging.ILogger
- 使用
ILogger
using Microsoft.Extensions.Logging;
public class HomeController : Controller
{
ILogger _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
_logger.LogInformation("Controller instantiated");
}
}
使用Microsoft.Extensions.Logging;
公共类HomeController:控制器
{
ILogger\u记录器;
公共家庭控制器(ILogger记录器)
{
_记录器=记录器;
_logger.LogInformation(“控制器实例化”);
}
}
对于其他项目中的其他类,只需确保您依赖默认的ILogger接口,而不是Serilog的实现。这还有一个好处,即如果您以后要替换Serilog,您可以这样做,而不必在其他项目中删除对它的所有引用
using Microsoft.Extensions.Logging;
public class MyBusinessObject
{
ILogger _logger;
public MyBusinessObject(ILogger<MyBusinessObject> logger)
{
_logger = logger;
}
public void DoBusinessLog()
{
_logger.Information("Executing Business Logic");
}
}
使用Microsoft.Extensions.Logging;
公共类MyBusinessObject
{
ILogger\u记录器;
公共MyBusinessObject(ILogger记录器)
{
_记录器=记录器;
}
public void DoBusinessLog()
{
_logger.Information(“执行业务逻辑”);
}
}
出于某种原因,DI只在需要
ILogger
时才实例化一个Logger实例,而不需要ILogger
。为什么我不知道,也许其他人可以回答这个问题。谢谢,但我也遇到了同样的问题。我开始怀疑这是否不是Serilog问题,而是DI不工作的问题其他项目周期。例如,我设置了一个存储库并将其注入,它在我的web(根)中工作项目,但当我尝试将其注入其他对象时,它也会抛出一个缺少的param错误。我刚刚创建了一个新项目并得到了相同的结果。是否有可能缺少其他项目对DI的要求?我以前做过这件事,但它“刚刚起作用”。你解决了吗?我有完全相同的问题。出于其他原因(装饰者)我切换到Autofac进行依赖注入,现在它工作正常。很抱歉,我无法确定在切换IOC容器之前是否已修复它。我模糊地记得这是我的Serilog引用的问题。
using Microsoft.Extensions.Logging;
public class MyBusinessObject
{
ILogger _logger;
public MyBusinessObject(ILogger<MyBusinessObject> logger)
{
_logger = logger;
}
public void DoBusinessLog()
{
_logger.Information("Executing Business Logic");
}
}