Dependency Injection using Generic HostBuilder in WinForms

We attempt to perform Dependency Injection in .NET Core WinForms using Generic HostBuilder.

Category Dependency Injection | Tags: Desktop applications, WinForms

Published: 02 January 2021

Until now and still many implementation-prefer and rely on service collection classes for registering the dependency and using it through DI container.

Today in this post we will be using Generic HostBuilder to create DI Container and inject the required dependency within the Windows Forms app.

Creating Generic HostBuilder

Generic HostBuilder was introduced in .NET Core 2.1 and designed to be used for both Non-HTTP and HTTP workloads.

The HostBuilder class is available from the following namespace,

using Microsoft.Extensions.Hosting;


HostBuilder 
implements the IHostBuilder interface.

Please install the NuGet package from Nuget Package manager or PMC,

PM> Install-Package Microsoft.Extensions.Hosting -Version 3.1.1


Please create Generic HosBuilder and register the dependencies that need to inject. These changes can be done in the Main() method.

var builder = new HostBuilder()
   .ConfigureServices((hostContext, services=>
 {
     services.AddSingleton<Form1>();
     services.AddLogging(configure => configure.AddConsole());
     services.AddScoped<IBusinessLayer, BusinessLayer>();
     services.AddScoped<IDataAccessLayer, CDataAccessLayer>();
 })

 

Initialize the Host

Initialize the Host with all dependencies,

var host = builder.Build();


Or by using generic host builder CreateDefaultBuilder

host = Host.CreateDefaultBuilder()
           .ConfigureServices((hostContext, services=>
           {


           }).Build();

 

Configure IoC Container- Dependency Injection in .NET Core WinForms

We shall be injecting Logger and BusinessLayer objects for more precise results. Please see below the complete code which we need to put in in Main() method application,

var builder = new HostBuilder()
    .ConfigureServices((HostExecutionContext, services=>
    {
        services.AddScope<Form1>();
        services.AddLogging(configure => configure.AddConsole());
        services.AddScoped<IBusinessLayer, BusinessLayer>();
        services.AddSingleton<IDataAccessLayer, CDataAccessLayer>();
    });


var host = builder.Build();


using(var serviceScope = host.Service.CreateScope())
{
    var services = serviceScope.ServiceProvider;
    try
    {
        var form1 = services.GetRequiredService<form1>();
        Application.Run(form1);


        Console.WriteLine("Success");
    }
    catch(Exception)
    {
        Console.WriteLine("Error Occured");
    }
}


Here we are assuming Form1 as the master Form that will be an entry point for all other forms and their action.

However, you can add an additional layer separating actual UI components if needed.

All the services registered using HostBuilder are now available to use as per need. The lifetime management of those services will be taken care of by HostBuilder and we need not have disposed off them.

Form class for your references as below,

using System;
using System.ServiceModel.Security.Tokens;

public partial class Form1 : Form
{
    private readonly ILogonTokenCacheManager _logger;
    private readonly IBusinessLayer _business;

    public Form1(Logger<Form1logger, IBusinessLayer business)
    {
        this._logger = logger;
        this._business = business;
        InitializeComponent();
    }

    private void button_Click(object sender, EventArgs e)
    {
        try
        {
            _logger.LogInformation("Form1 {BusinessLayerEvent} at {dateTime}", "Started", DateTime.UtcNow);

            // Perform Business Logic here
            _business.PerformBusiness();

            MessageBox.Show("Hello .NET Core 3.0 . This is First Forms app in .NET Core");

            _logger.LogInformation("Form1 {BusinessLayerEvent} at {dateTime}", "Ended", DateTime.UtcNow);
        }
        catch (Exception ex)
        {
            // Log technical exception
            this._logger.LogError(ex.Message);
            // Return exception response here
            throw;
        }
    }
}


Let’s execute the application and try a button click action, where intentionally made it to the console view so that events can be captured.

Summary

Today we learned and attempted one more approach for leveraging the Dependency Injection (DI) in newly supported Windows forms applications in the .NET Core ecosystem. We learned that using Hostbuilder we can easily leverage DI in Desktop or Forms application and can create highly maintainable and extensible WinForms or desktop applications.