未使用WebHost的.NET Core应用配置ASP.NET Core日志及源码查询
Great question! Let's walk through how to find the source code, understand the core concepts, and adapt this pattern for non-web .NET Core apps.
First off, all ASP.NET Core source lives in the dotnet/aspnetcore repo on GitHub—you just need to know where to look:
ConfigureLogging: This isn't exclusive to web apps—it's part of the cross-cutting logging infrastructure. You'll find its implementation in theMicrosoft.Extensions.Loggingnamespace, specifically in files likeLoggingBuilderExtensions.csunder thesrc/Logging/Logging.Extensions/srcdirectory of the repo. The method's core job is to add logging-related services to the app'sIServiceCollectionand let you configure providers (like Console, Debug, or third-party tools) and log levels.UseStartup: This is web-host specific, so you'll locate it inWebHostBuilder.csundersrc/Hosting/Hosting/src. What it does is pretty straightforward: it takes yourStartupclass, calls itsConfigureServicesmethod to populate the DI container with your app's services, and wires up theConfiguremethod to set up the HTTP request pipeline (the latter is web-only, but the DI registration part is totally reusable).
Pro tip: If you're using Visual Studio or Rider, you can right-click on these methods and select "Go to Definition"—if you have symbol sources enabled, it'll take you straight to the decompiled source, and you can even navigate to the repo from there.
The key ideas behind these methods that you can adapt for non-web apps are:
- Centralized Dependency Injection (DI): Both
ConfigureLoggingandUseStartupbuild on .NET's built-in DI system. They add services to anIServiceCollection, which is then used to build anIServiceProvider—the container that resolves your app's dependencies. - Unified Configuration Root: ASP.NET Core uses a single
IConfigurationroot that pulls settings from multiple sources (appsettings.json, environment variables, command-line args). This same system works for non-web apps too. - Modular Setup: These methods let you split configuration into logical chunks (like logging setup vs. business services) instead of clumping everything in one place, making your code cleaner and more maintainable.
You don't need WebHost or WebHostBuilder to get this functionality. Instead, use the Generic Host (HostBuilder), which is designed for all .NET app types and uses the same DI and configuration infrastructure as ASP.NET Core. Here's a step-by-step example:
Step 1: Add Required Packages
First, install the necessary NuGet packages if you haven't already:
dotnet add package Microsoft.Extensions.Hosting dotnet add package Microsoft.Extensions.Logging.Console
Step 2: Build the Host with Logging and Service Configuration
This replicates the ConfigureLogging and Startup-style setup in a console app, including loading configuration from appsettings.json:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; var host = Host.CreateDefaultBuilder(args) // Replicate ConfigureLogging behavior (uses appsettings.json automatically) .ConfigureLogging((context, logging) => { // Pull logging settings from the "Logging" section of appsettings.json logging.AddConfiguration(context.Configuration.GetSection("Logging")); // Add console logging provider logging.AddConsole(); // Optional: Clear default providers if you want full control // logging.ClearProviders(); }) // Replicate Startup.ConfigureServices behavior .ConfigureServices((context, services) => { // Register your custom services here services.AddTransient<IMyBackgroundService, MyBackgroundService>(); }) .Build(); // Resolve and run your core service var service = host.Services.GetRequiredService<IMyBackgroundService>(); await service.RunAsync(); await host.RunAsync(); // Example service to demonstrate logging and DI public interface IMyBackgroundService { Task RunAsync(); } public class MyBackgroundService : IMyBackgroundService { private readonly ILogger<MyBackgroundService> _logger; public MyBackgroundService(ILogger<MyBackgroundService> logger) { _logger = logger; } public Task RunAsync() { _logger.LogInformation("Hello from a non-web app using ASP.NET Core-style logging!"); _logger.LogDebug("This debug message will show if enabled in appsettings.json"); return Task.CompletedTask; } }
Step 3: Optional: Use a "Startup" Class for Organization
If you prefer the clean separation of the Startup class pattern (like in web apps), you can create one and hook it up to the generic host:
public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } // Replicates Startup.ConfigureServices from web apps public void ConfigureServices(IServiceCollection services) { services.AddTransient<IMyBackgroundService, MyBackgroundService>(); } // Use this to initialize services after DI container is built public void Configure(IServiceProvider services) { var logger = services.GetRequiredService<ILogger<Startup>>(); logger.LogInformation("Non-web app initialized successfully!"); } }
Then update the host builder to use this class:
var host = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.AddConfiguration(context.Configuration.GetSection("Logging")); logging.AddConsole(); }) .ConfigureServices((context, services) => { // Initialize Startup and call ConfigureServices var startup = new Startup(context.Configuration); startup.ConfigureServices(services); // Register Startup itself if you need to call Configure later services.AddSingleton(startup); }) .Build(); // Call Configure to initialize app services var startup = host.Services.GetRequiredService<Startup>(); startup.Configure(host.Services);
This gives you the same organized, modular configuration pattern as ASP.NET Core web apps, but tailored to non-web scenarios.
内容的提问来源于stack exchange,提问作者Martin Plante

