Search code examples
c#asp.net-corewindows-services.net-6.0

WebApplicationBuilder vs IHostBuilder and lLogger


In a ASP.NET Core 6 project using a WebApplicationBuilder

<Project Sdk="Microsoft.NET.Sdk.Web">

I am able to get a logger right after it is defined. This is very useful so I can use the logger in the rest of the application configuration.

   _builder.Logging.ClearProviders()
      .AddLog4Net();

   var logger = _builder.Logging.Services.BuildServiceProvider()
       .GetService<ILoggerFactory>()
       .CreateLogger<MyType>();

But when I define a Worker Service using a IHostBuilder

<Project Sdk="Microsoft.NET.Sdk.Worker">

I am only able to configure logging, and cannot get a logger before after _builder.Build() which is to late.

_builder.ConfigureLogging(x =>
{
   x.ClearProviders();
   x.AddLog4Net();
};

var Logger = _builder.Build().Services.GetRequiredService<ILoggerFactory>()
    .CreateLogger<MyType>();

Why are these builders different and how do I get the logger right after defining it with ConfigureLogging?


Solution

  • I am able to get a logger right after it is defined. This is very useful so I can use the logger in the rest of the application configuration.

    This isn't the right thing to do. The logging is already going to be available in all parts of the application because its configured up front. You should have very little reason to call BuildServiceProvider in your own code. There are special cases, but if you're doing it, it's often a sign that something isn't being done correctly. Why? Well it creates another copy of the service provider, which means a different copy of each singleton service and you're not disposing it.

    Why are these builders different and how do I get the logger right after defining it with ConfigureLogging?

    We've slowly moving away from the deferred hosting building model (callbacks) and moving to something more linear but we haven't done this change for the worker service as yet.

    That said, there is an issue with not being able to log at startup because the logger is part of that initial wire up logic (chicken and egg problem). You can create another logging for startup purposes and then use the logger created by the DI container throughout the rest of your application.