Exploring Transient, Scoped, and Singleton using .NET and C#
A Quick Guide to Transient, Scoped, and Singleton in C#
In C#, the Transient
, Scoped
, and Singleton
scopes are options for controlling the lifetime of objects which are created by dependency injection.
Transient
Transient
objects are created each time they are requested. This means that if a Transient
is injected into multiple consumers, each consumer will receive a separate instance of the object.
Scoped
Scoped
objects are created once per request. This means that if a Scoped
is injected into multiple consumers within the same request, they will all receive the same instance of this object. However, if the object is injected into multiple consumers in different requests, each request will receive its own instance of the object.
Singleton
Singleton
objects are created the first time they are requested, and the same instance is used for all subsequent requests. This can be useful if you want to ensure that all consumers of a service are using the same instance of the object.
It is important to note that the Singleton
should be used with caution. If for example the Singleton
instance is modified simultaneously by multiple consumers. This can cause concurrency issues.
Code Example
Here is an example of using the scopes in a .NET project. This example shows how to register a service with .NET dependency injection system, and how to inject and use the service in a consumer class.
First, let’s define the service interface and its implementation:
public interface IMyService
{
void DoWork();
}
public class MyService : IMyService
{
public void DoWork()
{
Console.WriteLine("Doing work in MyService");
}
}
Next, we can inject and use the IMyService
service in a consumer class:
public class Consumer
{
private readonly IMyService _myService;
public Consumer(IMyService myService)
{
_myService = myService;
}
public void DoWork()
{
_myService.DoWork();
}
}
Use Transient
We can register the Transient
service in the ConfigureServices
method of the Startup
class:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IMyService, MyService>();
}
In this example, each time the Consumer
class is created or the DoWork
method is called, a new instance of the MyService
class will be created and injected into the Consumer
class.
Use Scoped
We can register the Scoped
service in the ConfigureServices
method of the Startup
class:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IMyService, MyService>();
}
In this example, the MyService
class will be created the first time it is requested within a given request, and the same instance will be used for all subsequent requests for the MyService
class within the same request. If the Consumer
class or the DoWork
method is called in a different request, a new instance of the MyService
class will be created and injected.
Use
Singleton
We can register the Singleton
scope service in the ConfigureServices
method of the Startup
class:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IMyService, MyService>();
}
In this example, the MyService
class will be created the first time it is requested, and the same instance will be used for all subsequent requests for the MyService
class.
Conclution
In general, it’s best to use the Transient
scope whenever possible, and to use the Scoped
or Singleton
scopes only when necessary to maintain state or ensure that all consumers are using the same instance of a service.
Thank you for reading! I hope that this information has been helpful to you.
If you found this information useful, please consider giving it a “clap” to help others find it more easily.