Required environment:
- Visual Studio 2017 or 2019
- .Net core from version 2.1, in this example I used .net core version 3.1.
To config dependency injection in .Net Core console application, after creating the project you have to install package DependencyInjection
from Nuget:
Or you can install from Package Manager with the command below:
Install-Package Microsoft.Extensions.DependencyInjection -Version 3.1.8
And now I create some services to register it to the DI container.
public interface INumberService
{
List<int> GetEvenNumber(int from, int to);
}
public class NumberService : INumberService
{
public List<int> GetEvenNumber(int from, int to)
{
if (from <= 0 && to <= 0) return null;
if (from > to) return null;
List<int> result = new List<int>();
for(int i = from; i<= to; i++)
{
if(i % 2 == 0)
{
result.Add(i);
}
}
return result;
}
}
Inside the Main
method of Program.cs
file, we can register service to DI container as below:
using Microsoft.Extensions.DependencyInjection;
// Step1: setup our DI
var serviceCollection = new ServiceCollection();
serviceCollection.AddTransient<INumberService, NumberService>();
//TODO: Add more service here....
After adding service to the DI container, we can call service to execute some method of that service. See some line code as below:
//Step 2: get service
var serviceProvider = serviceCollection.BuildServiceProvider();
var numberService = serviceProvider.GetService<INumberService>();
var lstNumber = numberService.GetEvenNumber(1, 15);
if(lstNumber != null && lstNumber.Any())
{
int stt = 0;
foreach(int number in lstNumber)
{
stt++;
Console.WriteLine(string.Format("Value of item {0} is: {1}", stt, number));
}
}
In that:
- BuildServiceProvider()
: Method helps to create a Microsoft.Extensions.DependencyInjection.ServiceProvider containing services from the provided Microsoft.Extensions.DependencyInjection.IServiceCollection.
- GetService()
: Method help get a service object from the service provider. If that service is not found, it will be returned null.
Dispose of all service: After all business code is done, you don’t want to use the serviceProvider
resource more, you have to release it to avoid unmanaged resources still existing in the memory ram.
// Step 3: dispose & release all service from service collection
if (serviceProvider is IDisposable)
{
((IDisposable)serviceProvider).Dispose();
}
Now we can run the application and see the result:
This is a basic way to use dependency injection in .Net Core console application. In addition, you can use Service Locator for replacement but I think it will be more complicated.
If you want to get service from any class, not only inside of the Main()
method, you have to change the serviceProvider
variable to the global scope or using the Singleton pattern to create the service provider as below:
The first. I created a ServiceCollectionHelper
class to manage all actions of service such as register service to DI container, get service, dispose of service…
public class ServiceCollectionHelper
{
private static ServiceCollectionHelper _instance;
private static readonly object ObjLocked = new object();
private static ServiceProvider _servicePrivider;
protected ServiceCollectionHelper()
{
}
public static ServiceCollectionHelper Instance
{
get
{
if (null == _instance)
{
lock (ObjLocked)
{
if (null == _instance)
_instance = new ServiceCollectionHelper();
}
}
return _instance;
}
}
/// <summary>
/// Register all service here
/// </summary>
public void RegisterService()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddTransient<INumberService, NumberService>();
// Add more service here
_servicePrivider = serviceCollection.BuildServiceProvider();
}
/// <summary>
/// Method help get service from service collection
/// </summary>
/// <typeparam name="T">Service you want to get</typeparam>
/// <returns></returns>
public T GetService<T>()
{
return _servicePrivider.GetService<T>();
}
/// <summary>
/// Dispose sevice collection
/// </summary>
public void Dispose()
{
if (_servicePrivider is IDisposable)
{
((IDisposable)_servicePrivider).Dispose();
}
}
}
Finally, you can register and call service from anywhere if you want. For example, I will code inside of Main()
method of Program.cs
to replace for first base way above:
ServiceCollectionHelper.Instance.RegisterService();
var numberService2 = ServiceCollectionHelper.Instance.GetService<INumberService>();
var lstNumber2 = numberService.GetEvenNumber(1, 15);
if (lstNumber2 != null && lstNumber2.Any())
{
int stt = 0;
foreach (int number in lstNumber2)
{
stt++;
Console.WriteLine(string.Format("Value of item {0} is: {1}", stt, number));
}
}
ServiceCollectionHelper.Instance.Dispose();
We also get the same result as above. Don’t forget that RegisterService()
method you only call one time in the Main()
method and the GetService()
method you can call from anywhere.
You also can apply this way to config Dependency injection for the Unit test project. I think it's a good option to do.
Conclusion
In this article, I just guide how to config dependency injection in .Net Core console application. I hope it brings some useful knowledge for you. If you have any questions you can leave a comment below for me.
You can refer to the source code from here.
Happy code!!!