首页 > 解决方案 > 在 C# 中使用 DI 登录到控制台

问题描述

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

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");
        }
    }
}

这就是每个 Log*() 调用所显示的内容:

fail: samples.Application[0]
      Error: In Application::Run
samples.Application: Error: Error: In Application::Run

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

有谁知道为什么?

标签: c#loggingdependency-injection

解决方案


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

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

为什么 addConsole() 不起作用?

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

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

为了在您的代码中解决此问题。在程序末尾添加 aConsole.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
        }

我还遇到了另一个解决方案,它是创建一个异步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");
        }

最终结果应该是这样的。

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");
        //}
    }

推荐阅读