Внедрение зависимостей ILoggerFactory, ILoggerFactory в промежуточном программном обеспечении, регистратор не выполняется

#c# #asp.net-core #dependency-injection #middleware #ilogger

#c# #asp.net-core #внедрение зависимостей #промежуточное программное обеспечение #ilogger

Вопрос:

Пытаюсь создать промежуточное программное обеспечение, которое регистрировало бы информацию для каждого запроса. ASP.NET Ядро 3.1 Изучение некоторых основ

Я пытаюсь понять какое-то странное поведение. Это мой конструктор для промежуточного программного обеспечения:

 public ContextRequestLoggingMiddleware( RequestDelegate next, ILoggerFactory loggerFactory ) {
    this._next = next;
    _logger = loggerFactory.CreateLogger( "ContextRequestLoggingMiddleware" );            
}
  

Использование этого работает так, как ожидалось. Сообщение регистрируется при каждом запросе:

 public async Task InvokeAsync (HttpContext context ) {
    _logger.LogInformation( "test from middleware" );
    await _next( context );    
}
  

Когда я использую код ниже:

 _logger = loggerFactory.CreateLogger<ContextRequestLoggingMiddleware>();
  

Выполнение продолжается _logger.LogInformation , но кажется, что оно не выполняется, ничего не регистрируется, никаких ошибок, никаких проблем, просто переходит к следующей строке кода. Просматривая _logger с помощью списка наблюдения, я не вижу никакой разницы между этими двумя подходами.

То же поведение, когда ничего не регистрируется, и ошибка не возникает, если я использую ILogger<T> :

 public ContextRequestLoggingMiddleware( RequestDelegate next, 
    ILogger<ContextRequestLoggingMiddleware> logger ) {
    this._next = next;
    _logger = logger;
}
  

Я не могу ввести обычный ILogger , поскольку он выдает ошибку времени выполнения:

Не удалось разрешить службу для типа ‘Microsoft.Расширения.Ведение журнала.ILogger’ при попытке активировать ‘Microsoft.AspNetCore.Builder.ContextRequestLoggingMiddleware’.

Снова проверяя объект, я не вижу разницы между различными подходами, которые я использовал. Так почему же это?Я бы ILogger<T> счел лучшим выбором, но почему он здесь не работает? У меня это работает в контроллере. Спасибо за объяснение.

Для контекста мой CreateHostBuilder :

 public static IHostBuilder CreateHostBuilder( string[] args ) =>
    Host.CreateDefaultBuilder( args )
        .ConfigureLogging( ( hostContext, loggingBuilder ) => {
            loggingBuilder.ClearProviders();
            loggingBuilder.AddConfiguration( hostContext.Configuration.GetSection( "Logging" ) );
            loggingBuilder.AddCustomFileLogger();
        }
        ).ConfigureWebHostDefaults( webBuilder => {
            webBuilder.UseStartup<Startup>();
        } );
  

И часть моего Startup класса:

 public void ConfigureServices( IServiceCollection services ) {
    services.AddControllers();
    services.AddDbContext<NPAContext>( options =>
         options.UseSqlServer( Configuration.GetConnectionString( cnnDB ) ) );
    services.AddAuthentication( options => {
        options.DefaultAuthenticateScheme = ApiKeyAuthenticationOptions.DefaultScheme;
        options.DefaultChallengeScheme = ApiKeyAuthenticationOptions.DefaultScheme;
    } )
        .AddApiKeySupport( options => { } );
    
    services.AddSingleton<List<JobEventDTO>>();            
}

public void Configure( IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory ) {
    if ( env.IsDevelopment() ) {
        app.UseDeveloperExceptionPage();
    }
    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseContextRequestLoggingMiddleware();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints( endpoints => {
        endpoints.MapControllers();
    } );
}
  

Редактировать
Разрешение:
Я допустил ошибку, и при создании класса ContextRequestLoggingMiddleware я поместил его в пространство Microsoft.AspNetCore.Builder имен. При этом единственным способом заставить logger работать в промежуточном программном обеспечении была передача ILoggerFactory и создание logger, но это работало только одним способом

 _logger = loggerFactory.CreateLogger( "ContextRequestLoggingMiddleware" )
  

Как только я поместил класс в другое пространство имен, начали работать и другие подходы

 _logger = loggerFactory.CreateLogger<ContextRequestLoggingMiddleware>()
  

А также передача ILogger<ContextRequestLoggingMiddleware> теперь работает

Итак, построение класса, как показано ниже, теперь работает для меня. Интересно, как изменение пространства имен заставляет его работать.

 namespace NPARetrieval.Middleware {
public class ContextRequestLoggingMiddleware {
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public ContextRequestLoggingMiddleware( RequestDelegate next, ILogger<ContextRequestLoggingMiddleware> logger ) {
        this._next = next;
        _logger = logger;
    }


    public async Task InvokeAsync (HttpContext context ) {
        _logger.LogInformation( "test from middleware" );
        await _next( context );    
    }
}
  

}

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

1. Что происходит, если вы явно вводите ILogger<ContextRequestLoggingMiddleware> ? Зачем использовать фабрику для начала?

2. @Nkosi Как написано, он компилируется и запускается, но строка кода _logger . LogInformation не выполняется, он просто проходит через него. Единственный способ, которым мне удалось зарегистрировать что-то из промежуточного программного обеспечения, — это использовать factory. В этом причина вопроса, пытаясь понять, почему работает только один подход, но не другие.

3. Проблема почти наверняка заключается в вашем вызове loggingBuilder.ClearProviders() .