Använd den generiska .NET-värden i en Windows Forms-app

.NET Generisk Värd är ett standardiserat sätt att konfigurera och köra program med inbyggt stöd för beroendeinjektion (DI), konfiguration och loggning. Windows Forms-appar innehåller inte generisk värdintegrering som standard, men du kan lägga till den. Den här artikeln visar hur du konfigurerar den Generiska Värden i en Windows Forms-app för att injicera tjänster i dina formulär.

Förutsättningar

Konfigurera den allmänna värden

Konfigurationen skiljer sig något mellan C# och Visual Basic. I C# konfigurerar du värden direkt i Program.cs. I Visual Basic använder du Application Frameworks start- och avstängningshändelser i ApplicationEvents.vb.

Konfigurera värden i Program.cs tillsammans med ApplicationConfiguration.Initialize():

  1. Anropa ApplicationConfiguration.Initialize() för att konfigurera Standardvärden för WinForms, inklusive visuella format, högt DPI-läge och standardteckensnitt.
  2. Skapa värden med CreateApplicationBuilder och registrera tjänster.
  3. Starta värden och lös huvudformuläret från DI.
  4. Skicka formuläret till Run.
  5. Stoppa och ta bort värden när formuläret har stängts.

Följande kod visar hela 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();
    }
}

Registrera och använda tjänster

När värden har konfigurerats registrerar du anpassade tjänster och matar in dem i dina formulär. Så här skapar och registrerar du en tjänst:

  1. Definiera ett tjänstgränssnitt:

    public interface IGreetingService
    {
        string GetGreeting();
    }
    
    Public Interface IGreetingService
        Function GetGreeting() As String
    End Interface
    
  2. Skapa en klass som implementerar gränssnittet. Klassen GreetingService matar in IConfiguration för att läsa hälsningsmeddelandet från 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. Registrera gränssnittet och implementeringen på byggarens Services egenskap, som visas i avsnittet Konfigurera den generiska värd.

Köra en värdbaserad tjänst

Den generiska värden kan också köra bakgrundstjänster som deltar i applikationens livscykel. Implementera IHostedService för att ta emot återanrop när värden startar och stoppar. Så här lägger du till en värdbaserad tjänst:

  1. Skapa en klass som implementerar IHostedService. Följande klass skriver till felsökningsutdata när värdtjänsten startar och stoppar.

    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. Registrera tjänsten med AddHostedService på byggarens Services egenskap, som visas i avsnittet Konfigurera den generiska hosten.

Värden anropar StartAsync vid start och StopAsync avstängning, så felsökningsutdata visas i utdatafönstret i Visual Studio.

Använda tjänster i ett format

Eftersom Form1 löses från DI-containern fungerar konstruktorinmatningen direkt:

  1. Lägg till konstruktorparametrar för varje tjänst som formuläret behöver.
  2. Lagra de injektade tjänsterna i privata fält.
  3. Använd tjänsterna i händelsehanterare eller andra metoder.
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

Lägg till konfiguration

CreateApplicationBuilder läses appsettings.json in automatiskt från utdatakatalogen. Så här lägger du till en konfigurationsfil:

  1. Skapa en appsettings.json fil i projektroten med dina konfigurationsvärden:

    {
      "GreetingMessage": "Hello from the Generic Host!"
    }
    
  2. Ange CopyToOutputDirectory till PreserveNewest i projektfilen så appsettings.json kopieras till utdatakatalogen:

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