Last time in the .NET Fundamentals series, we talked about Dependency injection and why it is so important in modern day programming. Today, we are going to take look into services... more along the lines of how to register those services for Dependency Injection.
In this series .NET Fundamentals, we started by taking a look at the concept of Dependency Injection and it's importance to modern day application development. We saw how loosely coupling components allows for easier maintenance and scalability. We took a look at how it can be implemented including a small demo featuring a service that inherits from an interface. This allows the service to be modified at any time without breaking things further down the application. The question becomes now, how do you get an application to recognize and use the service that you have created? In this article we are going to look at just that. We'll take a look at registering your services and the service lifetimes including what they are and how to use them.
In an application services should be decoupled. We showed the reasons why in our discussion on Dependency Injection. To do this, you don't want to call your service directly where it is needed. Instead, you want an intermediary to do this. This is done by creating and interface and having your service inherit from that interface
// Interface for loose coupling
public interface IArticleService
{
List<Article> GetArticles();
}
// Implementation of the interface
public class ArticleService : IArticleService
{
public List<Article> GetArticles()
{
return new List<Article>
{
new Article { Id = 1, Title = "Intro to Dependency Injection" },
new Article { Id = 2, Title = ".NET Best Practices" }
};
}
}
But now that we have this setup, we need to tell the application that the interface and this service are linked together. We do that by registering the service in the main method of the application.
In the days prior to .NET 6 there was a file that was part of any .NET application called startup.cs. This file generally held all of the services that would be injected into the program.cs file that was home to the main method of the program. This method was the starting point for any project. When .NET 6 was released, developers had gotten rid of the startup.cs file and moved everything to program .cs. This now became the main gateway to enter the program. It was also where service could be registered and injected into the application. these service were injected vis the lines in the file that started with something similar to “builder.Service.AddScoped….” These lines tend to intimidate any novice to .NET programming but they are fairly straight forward. It is also an error point when implementing DI. so a note here is that , if methods from your service are not working, check your program.cs file to make sure that the service is registered. So for the above example, how would we register this service?
In the code block above we can see the infamous line the really tells the application, “ when you are executing the method from the interface, look to the attached service to find the implementation of the method. This is because in an interface, there is no definition for the method. That's what keeps it loosely coupled. Now you can see how the link or registration of the service is done, but I bet you have questions about the part of the line of code that says, ”AddScoped"? That is the service lifetime.
The Service Lifetime tells the program about how each instance of the service is to be created and maintained by the application. There are three main service lifetimes, AddScoped, AddTransient, and AddSingleton.
AddScoped tells the application to create one instance of the service per request made by the user. This is useful when you are using the service to access data from a database. AddSingleton tells the application to create one instance of the service and use it for the entire life of the application. The use case here would be if you creating a service to log errors to a logging file. This service will continue to run as long as the application is running. And finally we have AddTransient, which tells the application to create an instance of the service every time the user makes a request. This would be used for services that may involve calculations and you need a clean service each time. As you learn to code, you will get use to knowing when you need to use each one of these lifetimes for your services.
So let's recap. You created an service that is inheriting from an interface. You register the service using the infamous, “builder.Services.Add….” line to your program.cs file linking the interface and the service together, telling the program when you are calling this service from the interface, you will find the implementation in this linked service file. And you have registered the service using the proper service lifetime. This is all an important part of Dependency Injection as a whole and now that we have gone through this, you are on your way to creating loosely coupled applications that are easily scaled and maintained making your life as a .NET Developer much easier and less stressful.
With 3 years experience in .NET Application Development, Jay still puts heavy committment towards learning new things in the space. He also has a passion for sharing his knowledge with those who wish to learn more about Full Stack .NET Development.
The more you learn, the more you learn there's more to learn! -Ramsey Lewis
Post a comment