Резервное поле типа ILogger, но введенный параметр типа ILogger

#c# #logging #dependency-injection #.net-core

#c# #ведение журнала #внедрение зависимости #.net-ядро

Вопрос:

Платформа ведения журнала .Net Core была разработана для использования с внедрением зависимостей. Например, если вы хотите добавить ведение журнала в класс с именем, MyClass вам нужно добавить ILogger<MyClass> параметр в конструктор класса:

 private readonly ILogger _logger;

MyClass(ILogger<MyClass> logger)
{
    _logger = logger;
}
  

Вопрос

Приведенный выше шаблон кодирования очень распространен (ИМХО), где в качестве резервного поля используется тип ILogger , а в качестве введенного параметра — тип ILogger<T> .

Почему бы нам не использовать резервное поле типа ILogger<MyClass> вместо ILogger ? Есть ли какая-либо разница?

Комментарии:

1. Если вы хотите быть экспертом в чем-то, вам нужно очень хорошо разбираться в основах.

Ответ №1:

ILogger<T> реализует ILogger . Вот почему вы можете назначить ILogger<T> для ILogger XML-комментария для ILogger<T> является:

Обычно используется для включения именованного ILogger из внедрения зависимостей.

Это говорит вам о том, что где-то какому-то коду нужен тип для создания регистратора для вас.

Если вы углубитесь в код для service.AddLogging() , то к ILoggerFactory добавятся ILogger<> и IServiceCollection . ILogger<T> имеет конкретную реализацию Logger<T> . Logger<T> вводит вышеупомянутый ILoggerFactory параметр, а затем вызывает CreateLogger передачу displayname типа T. LoggerFactory затем проверяет кэш уже созданных Logger файлов на основе T и возвращает его из кэша, добавляя его, если он не существует.

Таким образом, в принципе, это не добавляет дополнительной функциональности, но внутренне повышает производительность, сохраняя ILogger для каждого типа в кэше и передавая его вам при необходимости. <T> Необходим, потому что он используется при поиске по словарю / кешу

Ответ №2:

ILogger<T> определяется следующим образом:

 public interface ILogger<out TCategoryName> : ILogger
{
}
  

Я нашел этот код через «перейти к определению» в Visual Studio, но вы можете увидеть то же самое в теперь заархивированном репозитории здесь.

Исходя из этого, я делаю вывод, что ILogger<T> предоставляет простой способ задать категорию сгенерированного регистратора, но фактически не изменяет функциональность. Таким образом, я думаю, что использование ILogger для резервного поля прекрасно, поскольку ILogger<T> не добавляет никаких методов.

Ответ №3:

Разницы нет. ILogger<T> Интерфейс не добавляет никаких дополнительных методов или свойств к ILogger интерфейсу, поэтому вы вольны выбирать то, что вам больше нравится.

Вы можете просмотреть исходный код для каждого из них и код протоколирования ниже:

Код ILogger

Программный код ILoggerOfT