Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The .NET Generic Host provides a standardized way to configure and run applications with built-in support for dependency injection (DI), configuration, and logging. WPF applications don't include Host Builder integration by default, but you can add it. This article shows how to set up the Generic Host in a WPF app to inject services into your windows and use the full .NET hosting infrastructure.
Prerequisites
- The
Microsoft.Extensions.HostingNuGet package.
Set up the Generic Host
To integrate the Generic Host with your WPF app:
Remove
StartupUrifrom the application XAML file and wire up theStartupandExitevent handlers:<Application x:Class="HostBuilderApp.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Startup="Application_Startup" Exit="Application_Exit"> <Application.Resources> </Application.Resources> </Application>Build the host in the code-behind.
The
Application_Startupmethod creates the host with CreateApplicationBuilder, registers services on the Services property, starts the host, and shows the main window:private async void Application_Startup(object sender, StartupEventArgs e) { var builder = Host.CreateApplicationBuilder(); builder.Services.AddHostedService<SampleLifecycleService>(); builder.Services.AddSingleton<IGreetingService, GreetingService>(); builder.Services.AddSingleton<MainWindow>(); _host = builder.Build(); await _host.StartAsync(); MainWindow mainWindow = _host.Services.GetRequiredService<MainWindow>(); mainWindow.Show(); }Private Async Sub Application_Startup(sender As Object, e As StartupEventArgs) Dim builder = Host.CreateApplicationBuilder() builder.Services.AddHostedService(Of SampleLifecycleService)() builder.Services.AddSingleton(Of IGreetingService, GreetingService)() builder.Services.AddSingleton(Of MainWindow)() _host = builder.Build() Await _host.StartAsync() Dim mainWindow As MainWindow = _host.Services.GetRequiredService(Of MainWindow)() mainWindow.Show() End SubStop and dispose of the host when the application exits to clean up resources:
private async void Application_Exit(object sender, ExitEventArgs e) { using (_host) { await _host.StopAsync(); } }Private Async Sub Application_Exit(sender As Object, e As ExitEventArgs) Using _host Await _host.StopAsync() End Using End Sub
Create a service
The Services property in the previous section registers services with the DI container. To create a custom service:
Define a service interface:
public interface IGreetingService { string GetGreeting(); }Public Interface IGreetingService Function GetGreeting() As String End InterfaceCreate a class that implements the interface. The
GreetingServiceclass accepts IConfiguration through constructor injection to read values fromappsettings.json:public class GreetingService(IConfiguration configuration) : IGreetingService { public string GetGreeting() => configuration.GetValue<string>("GreetingMessage") ?? "Hello from the Generic Host!"; }Public Class GreetingService Implements IGreetingService Private ReadOnly _configuration As IConfiguration Public Sub New(configuration As IConfiguration) _configuration = configuration End Sub Public Function GetGreeting() As String Implements IGreetingService.GetGreeting Dim message As String = _configuration.GetValue(Of String)("GreetingMessage") If String.IsNullOrEmpty(message) Then Return "Hello from the Generic Host!" End If Return message End Function End Class
Run a hosted service
The Generic Host can also run background services that participate in the application's lifecycle. The host calls an IHostedService implementation when it starts and stops. To add a hosted service:
Create a class that implements IHostedService. The following class writes to the debug output when the host starts and stops:
public class SampleLifecycleService : IHostedService { public Task StartAsync(CancellationToken cancellationToken) { System.Diagnostics.Debug.WriteLine("SampleLifecycleService: Started."); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { System.Diagnostics.Debug.WriteLine("SampleLifecycleService: Stopped."); return Task.CompletedTask; } }Public Class SampleLifecycleService Implements IHostedService Public Function StartAsync(cancellationToken As CancellationToken) As Task Implements IHostedService.StartAsync System.Diagnostics.Debug.WriteLine("SampleLifecycleService: Started.") Return Task.CompletedTask End Function Public Function StopAsync(cancellationToken As CancellationToken) As Task Implements IHostedService.StopAsync System.Diagnostics.Debug.WriteLine("SampleLifecycleService: Stopped.") Return Task.CompletedTask End Function End ClassRegister the service with
AddHostedServiceon the builder'sServicesproperty, as shown in theApplication_Startupmethod in the Set up the Generic Host section.
The host calls StartAsync when starting and StopAsync when stopping, so the debug output appears in the Output window in Visual Studio.
Inject services into a window
The DI container injects dependencies into registered windows through constructor injection. To consume services in a window:
- Add constructor parameters for each service the window needs.
- Store the injected services in private fields.
- Use the services in event handlers or other methods.
The following code shows MainWindow accepting ILogger<MainWindow> and IGreetingService through its constructor:
public partial class MainWindow : Window
{
private readonly ILogger<MainWindow> _logger;
private readonly IGreetingService _greetingService;
public MainWindow(ILogger<MainWindow> logger, IGreetingService greetingService)
{
InitializeComponent();
_logger = logger;
_greetingService = greetingService;
}
private void OnGetGreetingClick(object sender, RoutedEventArgs e)
{
_logger.LogInformation("Get Greeting button clicked.");
GreetingText.Text = _greetingService.GetGreeting();
}
}
Class MainWindow
Private ReadOnly _logger As ILogger(Of MainWindow)
Private ReadOnly _greetingService As IGreetingService
Public Sub New(logger As ILogger(Of MainWindow), greetingService As IGreetingService)
InitializeComponent()
_logger = logger
_greetingService = greetingService
End Sub
Private Sub OnGetGreetingClick(sender As Object, e As RoutedEventArgs)
_logger.LogInformation("Get Greeting button clicked.")
GreetingText.Text = _greetingService.GetGreeting()
End Sub
End Class
Add configuration
CreateApplicationBuilder automatically loads appsettings.json when the file is in the output directory. To add a configuration file to your project:
Create an
appsettings.jsonfile in the project root with your configuration values:{ "GreetingMessage": "Hello from the .NET Generic Host!" }Set
CopyToOutputDirectorytoPreserveNewestin the project file so the file copies to the output directory:<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net10.0-windows</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <UseWPF>true</UseWPF> </PropertyGroup> <ItemGroup> <None Update="appsettings.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.*" /> </ItemGroup> </Project>
Related content
.NET Desktop feedback