在 Clean Architecture 中为 Autofac 实施 Serilog 上下文记录器注入的正确方法是什么?
What is the proper way to implement Serilog Contextual logger injection for Autofac in Clean Architecture?
到目前为止,我正在尝试在我的 Clean Architecture SPA 核心应用程序中为 Autofac 实施 Serilog 上下文记录器注入。
项目结构:
在我的项目中,Autofac 在 Infrastructure CL 项目中,如下所示:
参考代码:
public static class ContainerSetup
{
public static IServiceProvider InitializeWeb(Assembly webAssembly, IServiceCollection services) =>
new AutofacServiceProvider(BaseAutofacInitialization(setupAction =>
{
setupAction.Populate(services);
setupAction.RegisterAssemblyTypes(webAssembly).AsImplementedInterfaces();
}));
public static Autofac.IContainer BaseAutofacInitialization(Action<ContainerBuilder> setupAction = null)
{
var builder = new ContainerBuilder();
var coreAssembly = Assembly.GetAssembly(typeof(BaseEntity));
var infrastructureAssembly = Assembly.GetAssembly(typeof(P2PRepository));
builder.RegisterAssemblyTypes(coreAssembly, infrastructureAssembly).AsImplementedInterfaces();
setupAction?.Invoke(builder);
return builder.Build();
}
}
并在 Startup class 中注册 Autofac 容器,如下所示:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
return ContainerSetup.InitializeWeb(Assembly.GetExecutingAssembly(), services);
}
我尝试了什么?
我已在我的 Web 项目中成功实施 Serilog
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File(
@"D:\home\LogFiles\Application\myapp.txt",
rollingInterval: RollingInterval.Day,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
)
.CreateLogger();
try
{
Log.Information("Starting web host");
CreateWebHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog();
}
在 serilog 及其依赖项之上实现之后,我发现 Serilog 也为 Autofac 提供了实现。所以,我很困惑我应该在 Web 项目还是基础设施项目中在哪里使用 Serilog 的实际实现?我是否应该从我的 program.cs
文件中恢复所有代码并实施 Serilog 并使用以下代码在基础设施项目中安装它的依赖项?
首先安装Serilog依赖:
Install-Package AutofacSerilogIntegration
Then when configuring the Autofac container, call RegisterLogger():
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
var builder = new ContainerBuilder();
var coreAssembly = Assembly.GetAssembly(typeof(BaseEntity));
var infrastructureAssembly = Assembly.GetAssembly(typeof(P2PRepository));
builder.RegisterAssemblyTypes(coreAssembly, infrastructureAssembly).AsImplementedInterfaces();
setupAction?.Invoke(builder);
builder.RegisterLogger(); // Here register serilog
return builder.Build();
简单的问题是:
在我的 Clean 项目中实施 SerilogAutofac 集成的正确方法是什么?
将 Autofac
与 ASP.NET Core 2.1 和 2.2 连接起来的推荐方法是使用:
services.AddAutofac();
官方文档中的代码示例说明了您 return IServiceProvider
:
is the old, not recommended way, and is NOT SUPPORTED in ASP.NET Core
3.0+.
在 Autofac
注册服务后,您只需使用 Startup
class 中的方法注册依赖项:
public void ConfigureContainer(ContainerBuilder builder)
{
// Register your own things directly with Autofac, like:
builder.RegisterModule(new MyApplicationModule());
}
Link 文档是 here.
一旦 Autofac
正确连接,taste/opinion 如何注册 Serilog
就是问题,因为依赖项解析器将正确解析所有注册(Autofac
和 IServiceCollection
).我更喜欢尽可能通过内置 IServiceCollection
保持注册,因为它们是标准且更熟悉的方法。所以我会保留 UseSerilog()
版本。
更新:第二个想法,你必须选择 UseSerilog()
,因为那是注册 Serilog
ASP.NET ILoggerFactory
的实现应该用于日志记录。另一方面,builder.RegisterLogger();
仅向 Autofac 注册 Serilog 的 ILogger
。它不会将任何东西连接到 MVC。
关于您在 CL
项目中的 InitializeWeb
方法,在一个 DLL 中混合 ASP.NET 核心层和数据层依赖项时我会小心。如果 CL
项目可能会在多个项目的可重用 Nuget
包中发展,那么在 dll 中具有 ASP.NET 核心的硬编码版本可能是个问题。
What is the proper way to implement SerilogAutofac integration in my Clean project?
这是一个基于意见的问题,意味着对此没有单一的答案。
在我的看来,请记住要为 Autofac 实施 Serilog 上下文记录器注入,你正在做 两件事:
- 添加 Serilog
- 使用 Autofac 添加上下文记录器
Main
中的代码是for the first purpose as per the instruction。请记住,这纯粹是与 ASP.Net Core 集成的 Serilog。所以,到目前为止,没有涉及 Autofac。也就是说,如果您从项目中删除 Autofac 依赖项,您的应用程序仍应使用 Serilog。
ContainerSetup
中的代码是您将 Autofac 引入 ASP.NET Core 的地方,从那以后,ASP.NET Core 知道使用 Autofac 作为 DI 容器。如果您想 使用 Autofac 专门配置上下文记录器,那么 ContainerSetup
是正确的地方。
话虽如此,为了帮助决定在哪里配置记录器,请问自己一个简单的问题:
不管Autofac你要Serilog吗?
如果是,则不要在您的 Autofac 特定类型中初始化 Serilog 记录器。
到目前为止,我正在尝试在我的 Clean Architecture SPA 核心应用程序中为 Autofac 实施 Serilog 上下文记录器注入。
项目结构:
在我的项目中,Autofac 在 Infrastructure CL 项目中,如下所示:
参考代码:
public static class ContainerSetup
{
public static IServiceProvider InitializeWeb(Assembly webAssembly, IServiceCollection services) =>
new AutofacServiceProvider(BaseAutofacInitialization(setupAction =>
{
setupAction.Populate(services);
setupAction.RegisterAssemblyTypes(webAssembly).AsImplementedInterfaces();
}));
public static Autofac.IContainer BaseAutofacInitialization(Action<ContainerBuilder> setupAction = null)
{
var builder = new ContainerBuilder();
var coreAssembly = Assembly.GetAssembly(typeof(BaseEntity));
var infrastructureAssembly = Assembly.GetAssembly(typeof(P2PRepository));
builder.RegisterAssemblyTypes(coreAssembly, infrastructureAssembly).AsImplementedInterfaces();
setupAction?.Invoke(builder);
return builder.Build();
}
}
并在 Startup class 中注册 Autofac 容器,如下所示:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
return ContainerSetup.InitializeWeb(Assembly.GetExecutingAssembly(), services);
}
我尝试了什么?
我已在我的 Web 项目中成功实施 Serilog
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File(
@"D:\home\LogFiles\Application\myapp.txt",
rollingInterval: RollingInterval.Day,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
)
.CreateLogger();
try
{
Log.Information("Starting web host");
CreateWebHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog();
}
在 serilog 及其依赖项之上实现之后,我发现 Serilog 也为 Autofac 提供了实现。所以,我很困惑我应该在 Web 项目还是基础设施项目中在哪里使用 Serilog 的实际实现?我是否应该从我的 program.cs
文件中恢复所有代码并实施 Serilog 并使用以下代码在基础设施项目中安装它的依赖项?
首先安装Serilog依赖:
Install-Package AutofacSerilogIntegration
Then when configuring the Autofac container, call RegisterLogger():
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
var builder = new ContainerBuilder();
var coreAssembly = Assembly.GetAssembly(typeof(BaseEntity));
var infrastructureAssembly = Assembly.GetAssembly(typeof(P2PRepository));
builder.RegisterAssemblyTypes(coreAssembly, infrastructureAssembly).AsImplementedInterfaces();
setupAction?.Invoke(builder);
builder.RegisterLogger(); // Here register serilog
return builder.Build();
简单的问题是:
在我的 Clean 项目中实施 SerilogAutofac 集成的正确方法是什么?
将 Autofac
与 ASP.NET Core 2.1 和 2.2 连接起来的推荐方法是使用:
services.AddAutofac();
官方文档中的代码示例说明了您 return IServiceProvider
:
is the old, not recommended way, and is NOT SUPPORTED in ASP.NET Core 3.0+.
在 Autofac
注册服务后,您只需使用 Startup
class 中的方法注册依赖项:
public void ConfigureContainer(ContainerBuilder builder)
{
// Register your own things directly with Autofac, like:
builder.RegisterModule(new MyApplicationModule());
}
Link 文档是 here.
一旦 Autofac
正确连接,taste/opinion 如何注册 Serilog
就是问题,因为依赖项解析器将正确解析所有注册(Autofac
和 IServiceCollection
).我更喜欢尽可能通过内置 IServiceCollection
保持注册,因为它们是标准且更熟悉的方法。所以我会保留 UseSerilog()
版本。
更新:第二个想法,你必须选择 UseSerilog()
,因为那是注册 Serilog
ASP.NET ILoggerFactory
的实现应该用于日志记录。另一方面,builder.RegisterLogger();
仅向 Autofac 注册 Serilog 的 ILogger
。它不会将任何东西连接到 MVC。
关于您在 CL
项目中的 InitializeWeb
方法,在一个 DLL 中混合 ASP.NET 核心层和数据层依赖项时我会小心。如果 CL
项目可能会在多个项目的可重用 Nuget
包中发展,那么在 dll 中具有 ASP.NET 核心的硬编码版本可能是个问题。
What is the proper way to implement SerilogAutofac integration in my Clean project?
这是一个基于意见的问题,意味着对此没有单一的答案。
在我的看来,请记住要为 Autofac 实施 Serilog 上下文记录器注入,你正在做 两件事:
- 添加 Serilog
- 使用 Autofac 添加上下文记录器
Main
中的代码是for the first purpose as per the instruction。请记住,这纯粹是与 ASP.Net Core 集成的 Serilog。所以,到目前为止,没有涉及 Autofac。也就是说,如果您从项目中删除 Autofac 依赖项,您的应用程序仍应使用 Serilog。
ContainerSetup
中的代码是您将 Autofac 引入 ASP.NET Core 的地方,从那以后,ASP.NET Core 知道使用 Autofac 作为 DI 容器。如果您想 使用 Autofac 专门配置上下文记录器,那么 ContainerSetup
是正确的地方。
话虽如此,为了帮助决定在哪里配置记录器,请问自己一个简单的问题:
不管Autofac你要Serilog吗?
如果是,则不要在您的 Autofac 特定类型中初始化 Serilog 记录器。