Using Dependency Injection in a .NET Core Console/ Desktop Application
Today in this article, we will see using Dependency Injection in a .NET Core Console/ Desktop Application.
Unlike ASP.NET Core, an application like Form WPF, or Console apps which are highly useful applications don’t have a Dependency Injection( DI) framework supported by default.
Today in this article, we will cover below aspects,
As we know .NET Core framework has brought in and leveraged the Explicit Dependency Injection (DI) principle very well and almost every functionality/service used in the application can be injected through DI.
Ultimately your container controls the lifetime of services used and the consumer need not have to worry about disposing of them once after every use.
“Only pay for what you use”
It is a simple concept, you inject and use services that you need, making your application highly efficient and lightweight.
There are a lot of benefits of the DI approach like,
- Separation of concern
- Independently deployable unit
- Easily Testable units
- High performance
- Easy maintenance
One should also understand that every good pattern, if not used properly for a given context, can become an anti-pattern too. Unlike ASP.NET core applications, we don’t have a pipeline in non-ASP.NET core apps.
So here we shall be using the entry point of applications as a pipeline.
As an example – the Main() method is the entry point for the Console application.
Here we will use the same concept, and create a new entry point called Run(). Importantly this Run will be called using instances that are created using ServiceProvider and ServiceColletion class.
I believe a similar concept of the entry point as pipeline can be leveraged in the Form/WPF Desktop application. I shall surely give it a try in the coming days using .NET Core 3.0.
Getting Started
Here is an example of a project structure ultimately we will be dealing with.
This early structure will give you a clear idea of what ultimately we want to achieve at the end of this article.
This application looks like a real project which has an Application Layer, a Business Layer, and a Data Access Layer.
I’m here to try to inject all the dependencies required from your app layer using the ServiceColletion class and ServiceProvider class to leverage DI.
So we will be doing DI for the below types from our UI layer itself.
<IBusinessLayer, CBusinessLayer>
<IDataAccessLayer, CDataAccessLayer>
Let’s create a .NET Core 3.1 Console application,
Update the Main() method as below,
static void Main(string[] args)
{
var services = new ServiceCollection();
ConfigureServices(services);
using (ServiceProvider serviceProvider
= services.BuildServiceProvider())
{
MyApplication app = serviceProvider.GetService<MyApplication>();
app.Run();
}
}
Add ConfigureServices() method as below,
Please add below NuGet packages explicitly to your application,
- Microsoft.Extensions.DependencyInjection
- Microsoft.Extensions.Logging
- Microsoft.Extensions.Logging.Console
Here we are explicitly injecting types like,
- MyApplication,
- CBusinessLayer
- CDataAccessLayer
- ILogger
Lifetime management of these types will be based on they are configured through service collection. Like singleton or scoped service behavior etc.
Here is the complete code for the Program.cs
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
ConfigureServices(services);
using (ServiceProvider serviceProvider =
services.BuildServiceProvider())
{
MyApplication app = serviceProvider.GetService<MyApplication>();
app.Run();
}
}
private static void ConfigureServices(ServiceCollection services)
{
services.AddLogging(configure => configure.AddConsole())
.AddTransient<MyApplication>()
.AddScoped<IBusinessLayer, CBusinessLayer>()
.AddSingleton<IDataAccessLayer, CDataAccessLayer>();
}
}
The business layer code is as below,
public class CBusinessLayer : IBusinessLayer
{
private readonly ILogger _logger;
private readonly IDataAccessLayer _dataAccess;
public CBusinessLayer(ILogger<CBusinessLayer> logger,
IDataAccessLayer dataAccess)
{
_logger = logger;
_dataAccess = dataAccess;
}
public IDataAccessLayer DataAccess => _dataAccess;
public void PerformBusiness()
{
_logger.LogInformation("BusinessLayer {BusinessLayerEvent} at {dateTime}", "Started", DateTime.UtcNow);
// Perform Business Logic here
_dataAccess.Create();
_logger.LogInformation("BusinessLayer {BusinessLayerEvent} at {dateTime}", "Ended", DateTime.UtcNow);
}
}
Once you execute the application here is the output execution with logging on the console,
Using a similar concept I have implemented Logging in a Console application. Please visit the below post for more details.
Implement DI using Generic HostBuilder
Dependency injection can be implemented using generic HostBuilder in a .NET Core console application. Please see the below article for more details,
- Generic HostBuilder– Dependency Injection using Generic HostBuilder in .NET Core Console application
Summary
Today we learned how to leverage the Dependency Injection (DI) principle in Console apps or Desktop apps types of NET Core applications.
We understood unlike ASP.NET Core-based applications like MVC or WebAPI apps, the .NET Core Console application doesn’t have dependency injection inbuilt framework. It also doesn’t have a pipeline preconfigured but with a few custom changes and best practices as mentioned above, we can very much achieve similar functionality and can create lightweight, maintainable, and performative Console applications.
Hope you liked this article! Please sound off your comments below.
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.
Nice Article, this is exactly what I was looking.
when I tried implement as per your example am getting below error…
Error: “Cannot resolve scoped service ‘RIUpdater.Service.IBridgeService’ from root provider.”
Thanks Venky. You can create a scope for the service host elements as explained in the article using generic host builder – Dependency Injection in Console app using generic HostBuilder – Part II
Hope that helps.
This is a really good article – thanks – Where in GitHub is the source?
Thanks for the article
Do you have the source code?
Thanks Mohammad, I shall soon put the complete code to GitHub.
Thanks. You explained this concept nicely.
Thanks Hikamu- Appreciate your feedback.