De .NET Generic Host gebruiken in een Windows Forms-app

De .NET Generic Host biedt een gestandaardiseerde manier om toepassingen te configureren en uit te voeren met ingebouwde ondersteuning voor afhankelijkheidsinjectie (DI), configuratie en logboekregistratie. Windows Forms-apps bevatten standaard geen algemene hostintegratie, maar u kunt deze wel toevoegen. In dit artikel wordt beschreven hoe u de algemene host instelt in een Windows Forms-app om services in uw formulieren te injecteren.

Vereiste voorwaarden

De algemene host instellen

De installatie verschilt enigszins tussen C# en Visual Basic. Configureer in C# de host rechtstreeks in Program.cs. Gebruik in Visual Basic de opstart- en afsluit-gebeurtenissen van Application Framework in ApplicationEvents.vb.

Configureer de host in Program.cs naast ApplicationConfiguration.Initialize().

  1. Aanroep ApplicationConfiguration.Initialize() om standaardinstellingen voor WinForms te configureren, waaronder visuele stijlen, hoge DPI-modus en standaardlettertypen.
  2. Bouw de host met CreateApplicationBuilder en registreer services.
  3. Start de host en los het hoofdformulier op vanuit DI.
  4. Geef het formulier door aan Run.
  5. Stop en verwijder de host nadat het formulier is gesloten.

De volgende code toont het volledige 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();
    }
}

Services registreren en gebruiken

Configureer de host, registreer aangepaste services en injecteer deze in uw formulieren. Een service maken en registreren:

  1. Een service-interface definiëren:

    public interface IGreetingService
    {
        string GetGreeting();
    }
    
    Public Interface IGreetingService
        Function GetGreeting() As String
    End Interface
    
  2. Maak een klasse waarmee de interface wordt geïmplementeerd. De GreetingService klasse injecteert IConfiguration die het begroetingsbericht leest van appsettings.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 Class
    
  3. Registreer de interface en implementatie op de Services-eigenschap van de builder, zoals weergegeven in de sectie De generieke host configureren.

Een gehoste service uitvoeren

De algemene host kan ook achtergrondservices uitvoeren die deelnemen aan de levenscyclus van de toepassing. Implementeer IHostedService voor het ontvangen van callbacks wanneer de host wordt gestart en gestopt. Een gehoste service toevoegen:

  1. Maak een klasse die IHostedService implementeert. De volgende klasse schrijft naar de foutopsporingsuitvoer wanneer de host wordt gestart en stopt:

    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 Class
    
  2. Registreer de service met AddHostedService op de eigenschap van de builder van Services, zoals wordt weergegeven in de sectie Set up the Generic Host.

De host roept StartAsync aan bij het opstarten en StopAsync bij het afsluiten, zodat de foutopsporingsuitvoer in het Uitvoer-venster in Visual Studio wordt weergegeven.

Services in een formulier gebruiken

Omdat Form1 wordt opgelost vanuit de DI-container, werkt constructor-injectie rechtstreeks:

  1. Voeg constructorparameters toe voor elke service die het formulier nodig heeft.
  2. Sla de geïnjecteerde services op in privévelden.
  3. Gebruik de diensten in gebeurtenishandlers of andere methoden.
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

Configuratie toevoegen

CreateApplicationBuilder laadt appsettings.json automatisch vanuit de uitvoermap. Ga als volgende te werk om een configuratiebestand toe te voegen:

  1. Maak een appsettings.json bestand in de hoofdmap van het project met uw configuratiewaarden:

    {
      "GreetingMessage": "Hello from the Generic Host!"
    }
    
  2. Stel CopyToOutputDirectory in op PreserveNewest in het projectbestand, zodat appsettings.json naar de uitvoermap wordt gekopieerd.

    <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>