How to Leverage IServiceCollection in Console Applications
Written on
Chapter 1: Introduction to IServiceCollection
In the realm of dependency injection, particularly with the built-in IServiceCollection, it often feels like we're confined to ASP.NET Core. However, what if we want to implement IServiceCollection in console applications? Are there viable alternatives? The answer is a resounding yes! In this article, I will reference a Microsoft Learn article and outline a simpler approach that you can execute directly in your browser using dotnetfiddle.
Chapter 2: Exploring Microsoft Learn's Approach
Microsoft Learn serves as an incredible repository of useful knowledge. I've been continually impressed by the wealth of information available there, especially since I previously relied heavily on MSDN for documentation and occasional examples.
However, I found myself slightly overwhelmed by the complexity of one particular article. If our primary aim is to utilize the IServiceCollection interface for familiar dependency injection, I would have preferred a more streamlined approach.
The tutorial provided an example that goes beyond the basics, showcasing the HostApplicationBuilder, which is used for dependency injection.
Section 2.1: Understanding HostApplicationBuilder
The example code provided in the Microsoft Learn article is as follows:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ConsoleDI.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddTransient<MyService>();
builder.Services.AddScoped<MyDependency>();
builder.Services.AddSingleton<AnotherService>();
using IHost host = builder.Build();
ExemplifyServiceLifetime(host.Services, "Lifetime 1");
ExemplifyServiceLifetime(host.Services, "Lifetime 2");
await host.RunAsync();
static void ExemplifyServiceLifetime(IServiceProvider hostProvider, string lifetime)
{
using IServiceScope serviceScope = hostProvider.CreateScope();
IServiceProvider provider = serviceScope.ServiceProvider;
ServiceLifetimeReporter logger = provider.GetRequiredService<ServiceLifetimeReporter>();
logger.ReportServiceLifetimeDetails($"{lifetime}: Call 1 to provider.GetRequiredService()");
Console.WriteLine("...");
logger = provider.GetRequiredService<ServiceLifetimeReporter>();
logger.ReportServiceLifetimeDetails($"{lifetime}: Call 2 to provider.GetRequiredService()");
Console.WriteLine();
}
While this example illustrates several concepts, my main concern is the necessity of creating an entire hosted application just to use IServiceCollection.
Section 2.2: Direct Use of IServiceCollection in Console Applications
Fortunately, it's not as complicated as it seems to implement this without the hosted application framework from Microsoft Learn. This is crucial for my goal of providing alternatives for those who wish to use IServiceCollection in a straightforward manner.
Here’s a simplified example that you can also find on dotnetfiddle:
using System;
using Microsoft.Extensions.DependencyInjection;
public class Program
{
public static void Main()
{
var services = new ServiceCollection();
services.AddSingleton<MyService>();
services.AddSingleton<MyDependency>();
using var serviceProvider = services.BuildServiceProvider();
var myService = serviceProvider.GetRequiredService<MyService>();
myService.DoTheThing();
}
}
public class MyService
{
private readonly MyDependency _myDependency;
public MyService(MyDependency myDependency)
{
_myDependency = myDependency;}
public void DoTheThing() =>
Console.WriteLine("Hello World!");
}
public class MyDependency
{
}
In this case, creating a new service collection is as simple as instantiating a new ServiceCollection. Notably, there’s no requirement for a hosted application or any additional builders, making it much more accessible. Additionally, the example on dotnetfiddle shows that you don't need to import any NuGet packages to implement this.
From this point, you can begin registering dependencies directly with the IServiceCollection:
services.AddSingleton<MyService>();
services.AddSingleton<MyDependency>();
After that, creating a service provider to resolve dependencies is straightforward:
using var serviceProvider = services.BuildServiceProvider();
var myService = serviceProvider.GetRequiredService<MyService>();
Conclusion: Simplifying Dependency Injection
In conclusion, you don’t need a hosted application to utilize IServiceCollection in console applications for dependency injection. While the Microsoft Learn article is thorough and filled with beneficial examples, it could have been more concise.
If you're eager to implement IServiceCollection in your console projects rather than using Autofac, feel free to explore! Even though I have a preference for Autofac in all my dependency injection endeavors, it's essential to understand the options available to you.
If you found this information helpful and are interested in further learning, consider subscribing to my free weekly software engineering newsletter. Additionally, check out my free videos on YouTube, where you can connect with a community of like-minded software engineers!
Chapter 3: Video Resources
To enhance your understanding, here are two valuable video resources:
Learn how to create a C# console application using dependency injection in this informative video.
This video compares registration callbacks with IServiceCollection and Autofac, providing insights into their differences and applications.