Как работает внедрение зависимости для ковариационного типа в .NET Core - PullRequest
0 голосов
/ 21 октября 2019

Недавно я работал с ASP.net core 3.0 и застрял. Как мы знаем, как инжектор конструктора работает для внедрения зависимостей в .NET Core.

например,

public class A: IA{
   private readonly IB<B> iB;
   public A(IB<B> iB){
       this.iB = iB;
   }
}

Разрешение зависимостей, как показано ниже.

IB<B> iB = new B();
IA iA = new A(iB);

Это нормально. я понял, но как насчет «универсального типа ковариации»

например ILogger<ControllerName>

См. приведенный ниже код

public class AController {
   private readonly ILogger<AController> iLogger;
   public AController(ILogger<AController> iLogger){
       this.iLogger = iLogger;
   }
}

, поэтому в данном случае он выглядит как AControllerполучать круговую ссылку. Если вы ищете определение ILogger, это похоже на

ILogger<out TCategoryName> : ILogger { }

Универсальный тип ковариации.

1 Ответ

0 голосов
/ 22 октября 2019

Для ILogger<out TCategoryName> : ILogger { }, это не будет ссылаться на TCategoryName, TCategoryName будет использоваться в качестве строки для указания category name во время регистрации.

Вы можете проверить исходный код для ILogger с помощью Ведение журнала .

Вот процесс.

Для ILogger<AController>, он создается LoggerFactoryExtensions

public static ILogger<T> CreateLogger<T>(this ILoggerFactory factory)
{
    if (factory == null)
    {
        throw new ArgumentNullException(nameof(factory));
    }
    return new Logger<T>(factory);
}

Дляnew Logger<T>(factory);, он получит имя категории с TypeNameHelper.GetTypeDisplayName(typeof(T), includeGenericParameters: false, nestedTypeDelimiter: '.')

public Logger(ILoggerFactory factory)
{
    if (factory == null)
    {
        throw new ArgumentNullException(nameof(factory));
    }

    _logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T), includeGenericParameters: false, nestedTypeDelimiter: '.'));
}

И затем он создаст регистратор с именем cateogoryname в качестве параметра

    public ILogger CreateLogger(string categoryName)
    {
        if (CheckDisposed())
        {
            throw new ObjectDisposedException(nameof(LoggerFactory));
        }

        lock (_sync)
        {
            if (!_loggers.TryGetValue(categoryName, out var logger))
            {
                logger = new Logger
                {
                    Loggers = CreateLoggers(categoryName),
                };

                (logger.MessageLoggers, logger.ScopeLoggers) = ApplyFilters(logger.Loggers);

                _loggers[categoryName] = logger;
            }

            return logger;
        }
    }

Во время процесса CreateLoggers он простоиспользуйте category name в качестве строки.

Для всего процесса он не создает instace для TCategoryName, поэтому он не получит циклическую ссылку.

...