4

我正在使用 .Net Core 3.1 XUnit 项目。

我创建了一个 SerivceCollection 并调用 AddLogging 扩展方法。然后我可以使用 LoggerFactory / ILoggerFactory 创建一个 ILogger 实例,当我调试时,我的 ServiceCollection 可以为这种类型提供一个 ServiceDescriptor:

Lifetime = Singleton, ServiceType = {Name = "ILogger`1" FullName = "Microsoft.Extensions.Logging.ILogger`1"}, ImplementationType = {Name = "Logger`1" FullName = "Microsoft.Extensions.Logging.Logger`1"}

我很好奇该刻度线在类型名称中的含义以及是否可以在不使用 LoggerFactory 的情况下解析 ILogger 实例。

以下是解决 ILogger`1 的几次失败尝试。最后一次调用 CreateLogger 有效。

[Fact]
        public void AddLogging_RegistersILogger()
        {
            var services = new ServiceCollection().AddLogging();

            var serviceProvider = services.BuildServiceProvider();

            var logger1 = serviceProvider.GetService<ILogger>(); // logger == null

            try
            {
                var logger2 = serviceProvider.GetService(typeof(ILogger<>));
            }
            catch (Exception e)
            {
                // Implementation type 'Microsoft.Extensions.Logging.Logger`1[T]' can't be converted to service type 'Microsoft.Extensions.Logging.ILogger`1[TCategoryName]'
            }

            try
            {
                var loggerTypes = Assembly.GetAssembly(typeof(ILogger)).GetTypes().Where(t => t.Name == "ILogger`1");
                var loggerType = loggerTypes.First();
                var logger3 = serviceProvider.GetService(loggerType);
            }
            catch(Exception e)
            {
                // Implementation type 'Microsoft.Extensions.Logging.Logger`1[T]' can't be converted to service type 'Microsoft.Extensions.Logging.ILogger`1[TCategoryName]'
            }

            var logger4 = serviceProvider.GetService<ILoggerFactory>().CreateLogger<DependencyInjectionTests>();

            Assert.NotNull(logger4);
        }
4

2 回答 2

2

打勾"ILogger`1"表示它是通用类型,即ILogger<CategoryName>

您可以为任何泛型类型注入ILogger<T>。泛型用于以方便的方式设置类别名称,例如ILogger<Controller>将具有"Microsoft.AspNetCore.Mvc.Controller"类别名称

通常的做法是每个类都有一个带有类名的记录器,例如,一个名为的类MyService将有一个记录器ILogger<MyService>

您可以注入ILogger<T>或使用ILoggerFactory

  • 注入ILogger<MyService>相当于调用loggerFactory.CreateLogger<MyService>()loggerFactory.CreateLogger("<namespace_of_my_service>.MyService")
于 2020-06-16T05:23:29.500 回答
0

我通过在 asp.net 核心中使用以下步骤实现 NLog 解决了这个问题

https://code-maze.com/net-core-web-development-part3/

Nuget:
1. NLog.Config
2. NLog.Extensions.Logging

Logging

functionality added to software so someone can get insight into the software

Logging as targets and rules.

nlog.config(将属性更改为始终复制)

1. the logfile name creates a file in the logs directory
2. debug is wrote to the logfile target

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Trace"
      internalLogFile="internallog.txt">
  <targets>
    <target name="logfile" xsi:type="File"
            fileName="${startupdir}\logs\${shortdate}_logfile.txt"
            layout="${longdate} ${level:uppercase=true} ${message}"/>
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="logfile" />
  </rules>
</nlog>

启动.cs

1. load the nlog.config
2. ConfigureLoggerService is part of the static class called Service Extensions.  Its job is to create a singleton task for the LoggerManager

public Startup(IConfiguration configuration)
        {
            LogManager.LoadConfiguration(@"nlog.config");
            Configuration = configuration;
            //_env = env;
        }

        public void ConfigureServices(IServiceCollection services)
        {
services.ConfigureLoggerService();
    }

服务扩展.cs

public static class ServiceExtensions
    {
        public static void ConfigureLoggerService(this IServiceCollection services)
        {
            services.AddSingleton<ILoggerManager, LoggerManager>();
        }
    }

记录器管理器.cs

1. use the dependency injected Logger for nLog to post based on type.

 public class LoggerManager : ILoggerManager
    {
        private static ILogger logger = LogManager.GetCurrentClassLogger();
        public void LogDebug(string message)
        {
            logger.Debug(message);
        }
        public void LogError(string message)
        {
            logger.Error(message);
        }
        public void LogInfo(string message)
        {
            logger.Info(message);
        }
        public void LogWarn(string message)
        {
            logger.Warn(message);
        }
    }
于 2021-12-10T20:49:26.260 回答