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. Windows Forms apps don't include Generic Host integration by default, but you can add it. This article shows how to set up the Generic Host in a Windows Forms app to inject services into your forms.
Prerequisites
- The
Microsoft.Extensions.HostingNuGet package.
Set up the Generic Host
The setup differs slightly between C# and Visual Basic. In C#, configure the host directly in Program.cs. In Visual Basic, use the Application Framework's startup and shutdown events in ApplicationEvents.vb.
Configure the host in Program.cs alongside ApplicationConfiguration.Initialize():
- Call
ApplicationConfiguration.Initialize()to configure WinForms defaults, including visual styles, high DPI mode, and default fonts. - Build the host with CreateApplicationBuilder and register services.
- Start the host and resolve the main form from DI.
- Pass the form to Run.
- Stop and dispose of the host after the form closes.
The following code shows the complete Program.cs:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace HostBuilderApp;
static class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
var builder = Host.CreateApplicationBuilder();
builder.Services.AddHostedService<SampleLifecycleService>();
builder.Services.AddTransient<Form1>();
builder.Services.AddSingleton<IGreetingService, GreetingService>();
IHost host = builder.Build();
host.Start();
Form1 mainForm = host.Services.GetRequiredService<Form1>();
Application.Run(mainForm);
host.StopAsync().GetAwaiter().GetResult();
host.Dispose();
}
}
Register and consume services
With the host configured, register custom services and inject them into your forms. To create and register a 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 injects IConfiguration to read the greeting message fromappsettings.json:public class GreetingService : IGreetingService { private readonly IConfiguration _configuration; public GreetingService(IConfiguration configuration) { _configuration = configuration; } public string GetGreeting() { return _configuration.GetValue<string>("GreetingMessage") ?? "Hello, World!"; } }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 message Is Nothing Then Return "Hello, World!" End If Return message End Function End ClassRegister the interface and implementation on the builder's
Servicesproperty, as shown in the Set up the Generic Host section.
Run a hosted service
The Generic Host can also run background services that participate in the application lifecycle. Implement IHostedService to receive callbacks when the host 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 the Set up the Generic Host section.
The host calls StartAsync on startup and StopAsync on shutdown, so the debug output appears in the Output window in Visual Studio.
Consume services in a form
Because Form1 is resolved from the DI container, constructor injection works directly:
- Add constructor parameters for each service the form needs.
- Store the injected services in private fields.
- Use the services in event handlers or other methods.
public partial class Form1 : Form
{
private readonly ILogger<Form1> _logger;
private readonly IGreetingService _greetingService;
public Form1(ILogger<Form1> logger, IGreetingService greetingService)
{
InitializeComponent();
_logger = logger;
_greetingService = greetingService;
}
private void ButtonGreet_Click(object sender, EventArgs e)
{
string greeting = _greetingService.GetGreeting();
lblGreeting.Text = greeting;
_logger.LogInformation("Greeting displayed: {Greeting}", greeting);
}
}
Public Class Form1
Private _logger As ILogger(Of Form1)
Private _greetingService As IGreetingService
Sub New(ILogger As ILogger(Of Form1), greetingService As IGreetingService)
InitializeComponent()
_logger = ILogger
_greetingService = greetingService
End Sub
Private Sub ButtonGreet_Click(sender As Object, e As EventArgs) Handles btnGreet.Click
Dim greeting As String = _greetingService.GetGreeting()
lblGreeting.Text = greeting
_logger.LogInformation("Greeting displayed: {Greeting}", greeting)
End Sub
End Class
Add configuration
CreateApplicationBuilder automatically loads appsettings.json from the output directory. To add a configuration file:
Create an
appsettings.jsonfile in the project root with your configuration values:{ "GreetingMessage": "Hello from the Generic Host!" }Set
CopyToOutputDirectorytoPreserveNewestin the project file soappsettings.jsonis copied to the output directory:<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net10.0-windows</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <UseWindowsForms>true</UseWindowsForms> </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