Dependency Injection is an important technique in Blazor Server .NET 6. In this tutorial, you will learn:
You can download the example code used in this topic on GitHub.
Dependency Injection will help you to create register a class/interface to the Service Provider, then the class/interface became a service. Whenever a service is required, the Service Provider will select the appropriated service in the pool and injecting it to the requesting class or component. The following image illustrates the Dependency Injection technique:
By using Dependency Injection technique, you will not worry about taking care of a service lifetime nor how to initialize the service. Your project will have decoupled classes that incredibly easy to maintain, testable, clean.
Before you can inject a service to a component, you first need to register the instance. There are several ways to register a service, you can register a service by its class or interface name. All services are registered at Program.cs
, the register process must be placed between WebApplication.CreateBuilder(args)
and builder.Build()
.
Assuming you have the following class:
public class ProcessService { public Guid ExampleId { get; set; } = Guid.NewGuid(); public void Process() { } }
Then you can register this class to become a service at Program.cs
. For example:
builder.Services.AddTransient<ProcessService>();
In the above example, transient is the scope of the service. You will learn about service scope later in this tutorial.
Assuming you have the following interface:
public interface IServiceInterface { string ExampleString { get; set; } }
And the following class:
public class ServiceWithInterface : IServiceInterface { public string ExampleString { get; set; } = "Blazor School"; }
Then you can register this class to become a service at Program.cs
. For example:
builder.Services.AddTransient<IServiceInterface, ServiceWithInterface>();
A service can have one or more parameter. Assuming you have the following class:
public class ServiceWithCustomData { public string ExampleString { get; set; } = ""; public ServiceWithCustomData(string exampleString) { ExampleString = exampleString; } }
Then you can pass the parameter when registering the service. For example:
builder.Services.AddTransient<ServiceWithCustomData>(serviceProvider => new ("Blazor School"));
A service can depend on another service. Assuming you have the following class:
public class DependentService { public ServiceWithCustomData ServiceWithCustomData { get; set; } public DependentService(ServiceWithCustomData serviceWithCustomData) { ServiceWithCustomData = serviceWithCustomData; } }
In this case, you must register the dependency service must. In this case, the DependentService
service depends on the ServiceWithCustomData
service so the ServiceWithCustomData
must be registered first. Once the ServiceWithCustomData
is register, you can proceed to register the DependentService
as follows:
builder.Services.AddTransient<DependentService>(serviceProvider => new(serviceProvider.GetRequiredService<ServiceWithCustomData>()));
You can also register the DependentService
with its interface name. It is irrelevant to the service is parameterized or not.
Once you have your service registered to the Service Provider, you can inject your service to a component or another service. If you registered your service with the class name, then you can inject the service to your component as follows:
@inject DependentService DependentService
Where:
If you registered your service with the interface name, you must use that interface to inject the service. For example:
@inject IServiceInterface ServiceWithInterface
Keep in mind that if you registered your service with class name and you use your interface name to inject the service, you will encounter the following error: Error: System.InvalidOperationException: Cannot provide a value for property '<Your Instance Name>' on type '<Your Class/Interface Name>'. There is no registered service of type '<Your Class/Interface Name>'
When you register a service, you will need to specify its scope. There are 3 scopes for you to specify:
The service with singleton scope will always have an instance in the Service Provider. The following image illustrates the singleton service scope:
The scoped services will always have an instance for each browser tab in the Service Provider. The following image illustrates the scoped service:
For transient services, the Service Provider will always create a new instance whenever it is injected. The following image illustrates the transient service: