【问题标题】:How to dependency inject Serilog into the rest of my classes in .NET Console App如何将 Serilog 依赖注入到 .NET 控制台应用程序中的其余类中
【发布时间】:2021-02-21 16:37:56
【问题描述】:

我开始使用Serilog,但我不知道如何将 ILogger 依赖注入到我的类中。如果我使用的是 ASP.NET Core 5,这很容易,但我使用的是 .NET Core 控制台应用程序。我该如何做类似的事情?

在使用 log4net 之前:

public class TestStrategy
{
    private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.Name);

    ...
}

我的 Serilog 记录器创建:

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

var logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

我必须 DI logger 进入所有课程吗?

【问题讨论】:

  • 你需要使用依赖注入框架。 ASP.NET Core 恰好有一个内置系统
  • @Xerillio,但 .NET 控制台应用程序中没有。
  • 没错。所以你需要在你的项目中添加一个 DI 框架(CastleWindsor、Ninject、Spring.NET、Autofac...)
  • @Xerillio,Autofac 似乎是最常用的,但我得学习如何去做 rn
  • 这不是一个真正的 Serilog 问题。有很多关于如何将 DI 添加到控制台应用程序的问答。

标签: c# .net dependency-injection serilog .net-5


【解决方案1】:

.Net Core 控制台应用程序中的内置 DI 机制可使用 Microsoft.Extensons.DependecyInjection 包 安装 DI 包后,可以通过实例化 ServiceCollection 实例来配置服务。 Serilog 日志功能可以添加如下。

var serviceProvider = new ServiceCollection()
                      .AddSingleton<IFoo, Foo>()
                      .AddSingleton<IBar, Bar>()
                      .AddLogging(builder =>
                      {
                          var logger = new LoggerConfiguration()
                          .MinimumLevel.Debug()
                          .WriteTo.Console()
                          .CreateLogger();

                          builder.AddSerilog(logger);
                      })
                      .BuildServiceProvider();

要封装 DI 配置,可以在类中实现配置。

public class Startup
        {
            private ServiceProvider _serviceProvider;
            public Startup()
            {
                ConfigureServices();
            }

            private void ConfigureServices()
            {
                _serviceProvider = new ServiceCollection()
                      .AddSingleton<IFoo, Foo>()
                      .AddSingleton<IBar, Bar>()
                      .AddLogging(builder =>
                      {
                          var logger = new LoggerConfiguration()
                          .MinimumLevel.Debug()
                          .WriteTo.Console()
                          .CreateLogger();

                          builder.AddSerilog(logger);
                      })
                      .BuildServiceProvider();
            }

            public ServiceProvider Provider { get { return _serviceProvider; } }
        }

然后在程序的main方法中,需要创建一个Startup类的新实例,并且可以使用启动实例的provider属性调用起点实现。

var startup = new Startup();
        startup.Provider.GetService<IFoo>().DoSomthing();

【讨论】:

  • 要使用AddSerilog 方法,您还需要Serilog.Extensions.Logging nuget 包。
  • 感谢您的回答!你能给出一个完整的例子吗?
  • 公平地说,这个 DI 框架并不比其他 DI 框架更内置,但它可能更轻量级(不过只是猜测)。
  • 在主机生成器上使用Serilog.Extensions.Hosting 来实现类似的UseSerilog 方法。无需调用 AddLogging,它会为主机正确设置所有记录器和提供程序
  • @Xerillio 实际上你是对的。由于 .net 核心功能被拆分为包,因此 DI 不再是内置功能。
【解决方案2】:

这是一个使用 .net 5 并使用 Microsoft.Extensions.DependencyInjection; 的示例:

程序.cs:

namespace dotnet.console.app
{
    using System.Threading.Tasks;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Serilog;
    class Program
    {
        static Task Main(string[] args) =>
            CreateHostBuilder(args).Build().RunAsync();

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((_, services) =>
                    services.AddHostedService<Worker>()
                            .AddLogging(builder =>
                            {
                                var logger = new LoggerConfiguration()
                                            .MinimumLevel.Debug()
                                            .WriteTo.Console()
                                            .CreateLogger();

                                builder.AddSerilog(logger);
                            }));
    }
}

Worker.cs

namespace dotnet.console.app
{
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;

    public class Worker : BackgroundService
    {
        private ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            this._logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                this._logger.LogInformation("Hello, Serilog!");
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
    <PackageReference Include="Serilog" Version="2.10.0" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
    <PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
  </ItemGroup>

</Project>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 2018-06-30
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    相关资源
    最近更新 更多