Dependency Injection and Custom Scope Creation in a .NET Console App
.NET has three ways of registering services into DI Container. The services can be registered as transient, scoped, or singleton, depending on the desired lifetime of the service.
Transient services are created each time they are requested.
Scoped services are created once per scope (In Web API, scoped services are created per request which is a Scope. But what about a Console App!!).
Singleton services are created once and reused throughout the application’s lifetime.
Let’s have a look at Transient and Singleton. After that we are going to describe the Scoped service in a Console App where there is no scope by default as the Web API. Let’s create a Console App, add an Interface IGenerator and a Class IdGenerator that implements IGenerator interface.
Transient: Now register the service (IGenerator) as a Transient (1) and resolve the service separately (2) to get the instances from DI (Dependency Injection) Container. Then run the project.
Let’s have a look at the console. We will see three different GUIDs since we registered the service as a Transient and DI Container is giving us different instances of IGenerator every time we request for it.
Singleton: Let’s add the service as a Singleton now and observe what we get in the console.
As expected, we are getting the same GUIDs since we added the service as a Singleton now and the DI container is always giving us the same IGenerator instance.
Scoped: Let’s add the service as Scoped and see what we get in the Console.
What happened here? We added the service as a Scoped and resolved it separately, but we are getting the same GUIDs every time and it’s behaving like a Singleton service. If we pay close attention to this, things will get clear to us. There is nothing wrong with the Scoped service and the output. In a console app there is no defined scope by default. So, no matter how many times we resolve the service, the DI container will give us the same instance.
Create a custom Scope: We are going to create custom scopes using IServiceScopeFactory and resolve the service in those scopes separately. Let’s see what we get in the console.
After observing the output in the console now we can say that we have three different scopes, and the instances are different per scope but the same in the same scope. That is why we are getting the same GUID in a scope and different GUIDs in different scopes. This is how a scoped service works. Whenever we request a registered Scoped service’s instance from one scope, the DI container will give us the same instance. But if the scopes are different then the DI container will give us different instances.