Configuring Dependency Injection in .NET Core Console Applications

Configuring DI in .net core console applications

.NET Core console applications do not have a startup file to register the dependencies.

In this post, we’ll see how we can create a dependency injection setup in .net core console applications.

A use case for this post

For this post, let’s create two services one that gives a message (MessageService) and the other to print a message (PrinterService).

The PrinterService has a Print method to print the message received from the MessageService. So, the PrinterService depends on the MessageService.

PrinterService uses MessageService

Here are the two services with code.

PrinterService.cs

using System;

namespace DIInConsole
{
    public interface IPrinterService
    {
        void PrintMessage();
    }

    public class PrinterService : IPrinterService
    {
        private IMessageService _messageService;
        public PrinterService(IMessageService messageService)
        {
            _messageService = messageService;
        }

        public void PrintMessage()
        {
            Console.WriteLine(_messageService.GetMessage());
        }
    }
}

MessageService.cs

using System;

namespace DIInConsole
{
    public interface IMessageService
    {
        MessageService MessageService { get; set; }

        string GetMessage();
    }

    public class MessageService : IMessageService
    {
        public string GetMessage()
        {
            return "This is a simple message.";
        }
    }
}

using ServiceCollection in the Program.cs file

Before we register our services, we’ve to install the Microsoft Dependency Injection package from Nuget.

With .NET CLI, you can install the package using the following command.

dotnet add package Microsoft.Extensions.DependencyInjection --version 3.1.4

We will use the ServiceCollection class in the above package to register our services to the DI container.

Here is our registration code for registering IMessageService and IPrinterService services.

 var serviceCollection = new ServiceCollection();
 serviceCollection.AddTransient<IMessageService, MessageService>();
 serviceCollection.AddTransient<IPrinterService, PrinterService>();

Once we register our services with the extension methods (AddTransient, AddScoped, AddSingleton), we will call the BuildServiceProvider on the serviceCollection object to return an instance of ServiceProvider.

var serviceProvider = serviceCollection.BuildServiceProvider();

With the ServiceProvider instance, we can get our service(s) from the registered services.

We will call GetRequiredService or GetService on the serviceProvider object to get our required service and invoke our method to get the output.

serviceProvider.GetService<IPrinterService>().PrintMessage();

That’s it! You should see our sample output in the console.

Miscellaneous Info.

What BuildServiceProvider does?

The BuildServiceProvider will just return a new instance of the ServiceProvider taking ServiceCollection instance as an argument in the constructor.

The BuildServiceProvider is just an extension method on the ServiceProvider class. Here is the original source code from github.

public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }

    if (options == null)
    {
        throw new ArgumentNullException(nameof(options));
    }

    return new ServiceProvider(services, options);
}

Difference between GetRequiredService and GetService

GetService() returns null if a service does not exist, GetRequiredService() throws an exception instead. If you’re using a third-party container, use GetRequiredService where possible – in the event of an exception, the third party container may be able to provide diagnostics so you can work out why an expected service wasn’t registered.

– Andrew Lock post on the difference

References

DI in Console applications
Difference between GetService and GetRequiredService in aspnet core
BuildServiceProvider source from github