Dependency Injection in WinForms

A simple approach of implementing Dependency Injection in WinForms desktop applications.

Category Dependency Injection | Tags: Desktop applications, WinForms

Published: 11 December 2020

DI is a simple concept where you inject and use the services that you need, making your application highly efficient and lightweight.

As already discussed in our previous article, there are a lot of benefits of DI approach like,

  • Separation of concern
  • Independently deployable unit
  • Easily Testable units
  • High performance
  • Easy maintenance

Here below I would like to inject the IBusinessLayer and ILogger object through Forms object.


Add ConfigureServices() method

Please add below ConfigureServices() method. This method can be used for registering all the required services within Service collection.

using System.ServiceModel.Configuration;

private static void ConfigureServices(ServiceElementCollection services)
{
    services.AddLogging(ConfigureServices => ConfigureServices.AddCOnsole())
        .AddScope<IBusinessLayer, CBusinessLayer>()
        .AddScope<IBusinessLayer, CBusinessLayer>()
        .AddSingleton<IDataAccessLayer, CDataAccessLayer>()
}


Let’s now add Form1 which is currently my master Form and has the UI logic. Please register Form1 to above as services.

services.AddScoped<Form1>();


Adding DI Container

Please update the Main() method as below.

We shall be injecting ILogger and IBusinessLayer object is as below,

[STAThread]
static void Main()
{
    Application.SetHighDpiMode(HighDpiMode.SystemAware);
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    var services = new ServiceCollection();

    ConfigureServices(services);

    using (ServiceProvider serviceProvider = services.BuildServiceProvider())
    {
        var form1 = serviceProvider.GetRequiredService<Form1>();
        Application.Run(form1);
    }
}

 

Here we are assuming Form1 is the master form that holds other forms together.

In the above code, we added Form, logging ILogger, and IBusinessLayer interface to services collection and built the ServiceProvider for the required services. With that, both the logger object and business object instance can be DI via Constructor injection as and when required in other layers.

Add IBusinessObject and ILogger using DI to Forms App

Complete sample code is as below,

public partial class Form1 : Form
{
    private readonly ILogger _logger;

    private readonly IBusinessLayer _business;
    public Form1(ILogger<Form1logger, IBusinessLayer business)
    {
        _logger = logger;
        _business = business;
        InitializeComponent();
    }

    private void button1_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
            _logger.LogError(ex.Message);
            //Return exception repsponse here
            throw;
        }

    }
}

 

Let’s execute the application, we shall see all layers executed with logging.


Summary

Today we learned an easy approach of adding the Dependency Injection (DI) in newly supported Windows forms applications in .NET Core 3.0 and above. We understood with few custom changes as mentioned above, we can very much leverage DI in Desktop or Forms application and can create maintainable and performative Win Form or Desktop applications.