在 C# 中使用 DI 登录到控制台

Ant*_*hin 6 c# logging dependency-injection

在这个简短的示例中,如果我只保留任何内容,则.AddConsole() 无论ConfigureServices日志级别如何,都不会记录到控制台,但如果我添加.AddConsole().AddDebug()所有消息,则会将所有消息记录到控制台 3 次!我缺少什么?谢谢!

namespace samples
{
    using System;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;

    public class Program
    {    
        public static void Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            ConfigureServices(serviceCollection);
            var serviceProvider = serviceCollection.BuildServiceProvider();

            var app = serviceProvider.GetService<Application>();
            app.Run();
        }

        private static void ConfigureServices(IServiceCollection services)
        {
            // Add Logger
            services.AddLogging(configure => configure.AddConsole().AddDebug());

            // Register Application
            services.AddTransient<Application>();
        }
    }

    public class Application {
        private readonly ILogger logger;

        public Application(ILogger<Application> logger)
        {
            this.logger = logger;
            this.logger.LogInformation("In Application::ctor");
        }

        public void Run() 
        {
            this.logger.LogInformation("Info: In Application::Run");
            this.logger.LogWarning("Warn: In Application::Run");
            this.logger.LogError("Error: In Application::Run");
            this.logger.LogCritical("Critical: In Application::Run");
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

这是每次 Log*() 调用时显示的内容:

fail: samples.Application[0]
      Error: In Application::Run
samples.Application: Error: Error: In Application::Run
Run Code Online (Sandbox Code Playgroud)

更新/解决方案 感谢@panoskarajohn 解决了这个问题。App.Run() 需要是异步的:更改app.Run(); => Task.Run(() => app.Run()).Wait(); public void Run() => public async Task Run() 并且应该在没有调试()选项的情况下工作我找不到任何关于为什么会发生这种情况的信息

有人知道为什么吗?

pan*_*ohn 4

我不知道为什么该选项没有发生这种情况addDebug()

我想它AddDebug()有一些特殊的配置,并在程序退出之前刷新输出。如果您有任何线索,请赐教

为什么 addConsole() 不起作用?

控制台日志记录发生在后台线程上。因此,如果应用程序退出太快,则记录器没有时间记录 -> https://github.com/aspnet/Logging/issues/631

所以这并不是说它没有发生。而是它没有时间写入控制台。应用程序退出太快。

为了在您的代码中解决这个问题。Console.Read()在程序末尾添加一个,这样程序就不会退出。

public static void Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            ConfigureServices(serviceCollection);
            var serviceProvider = serviceCollection.BuildServiceProvider();

            var app = serviceProvider.GetService<Application>();
            app.Run();
            Console.Read(); // So the application will not exit and there will be time for the background thread to do its job
        }
Run Code Online (Sandbox Code Playgroud)

我还遇到了另一个解决方案,它创建一个异步Task并等待它。

像这样更新代码。

public static void Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            ConfigureServices(serviceCollection);
            var serviceProvider = serviceCollection.BuildServiceProvider();

            var app = serviceProvider.GetService<Application>();
            Task.Run(() => app.Run()).Wait();
        }
// also update your Application run method
public async Task Run()
        {
            logger.LogInformation("Info: In Application::Run");
            logger.LogWarning("Warn: In Application::Run");
            logger.LogError("Error: In Application::Run");
            logger.LogCritical("Critical: In Application::Run");
        }
Run Code Online (Sandbox Code Playgroud)

最终结果应该是这样的。

public class Program
    {
        public static void Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            ConfigureServices(serviceCollection);
            var serviceProvider = serviceCollection.BuildServiceProvider();

            var app = serviceProvider.GetService<Application>();
            Task.Run(() => app.Run()).Wait();
            Console.Read();
        }

        private static void ConfigureServices(IServiceCollection services)
        {
            // Add Logger
            services.AddLogging(configure =>
            {
                configure.AddConsole();
            }).AddTransient<Application>();
        }
    }

    public class Application
    {
        private readonly ILogger<Application> logger;

        public Application(ILogger<Application> logger)
        {
            this.logger = logger;
            this.logger.LogInformation("In Application::ctor");
        }

        public async Task Run()
        {
            logger.LogInformation("Info: In Application::Run");
            logger.LogWarning("Warn: In Application::Run");
            logger.LogError("Error: In Application::Run");
            logger.LogCritical("Critical: In Application::Run");
        }

        //public void Run()
        //{
        //    logger.LogInformation("Info: In Application::Run");
        //    logger.LogWarning("Warn: In Application::Run");
        //    logger.LogError("Error: In Application::Run");
        //    logger.LogCritical("Critical: In Application::Run");
        //}
    }
Run Code Online (Sandbox Code Playgroud)