What is a service collection?
Service collections are a way of registering and resolving dependencies in C# applications using the built-in dependency injection (DI) system. Blazor Server is a web framework that allows you to run C# code on the server and interact with the user interface through a SignalR connection. To use service collections in Blazor Server, you need to register your services in the Program class, which is executed when the application starts.
How to register a service that implements an interface
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddServerSideBlazor();
//ILogService is a service we created that we want available throughout the application
builder.Services.AddScoped();
.
.
var app = builder.Build();
app.Run();
How to resolve a service in a Razor component
CoolComponent.razor
@inject ILogService logService
@code
{
protected override async Task OnInitializedAsync()
{
await logService.WriteLogAsync(Level.Info, "Cool Component Loaded");
}
}
This will inject an instance of ILogService into the CoolComponent and make it available as a property named service. You can then use this property to access the methods and properties of the service such as WriteLogAsync()
What happens when you have a lot of dependencies?
Sometimes Program.cs ends up getting large and unwieldly as an applications evolves and matures. Luckily the solution to this is the service collection extension pattern.
The solution: Service Extension Collection Pattern
- Improve the readability and maintainability of your code, by separating the service registration logic from the startup class.
- Enables you to group related services together in a single extension method, and use descriptive names for them.
- Facilitates the testing and mocking of your services, by allowing you to inject them as dependencies in your components and controllers.
- Supports the dependency injection principle of inversion of control, by letting the framework handle the creation and disposal of your services.
The service collection extension pattern is a way of organizing the dependency injection configuration for ASP.NET Core applications. It allows you to create extension methods on the IServiceCollection interface that register your services in a modular and reusable way. For example, you can create a method like builder.Services.AddOrderManagementServices() that registers all the services from your class library project .
This pattern can be useful for Blazor Server applications, which use ASP.NET Core as the host environment. Blazor Server applications are stateful and maintain a circuit between the server and the client. This means that you need to be careful about how you use singleton/scoped and transient services, as they may have a longer lifetime than expected. By using the service collection extension pattern, you can encapsulate the logic of registering your services with the appropriate lifetime and options.
One benefit of this pattern is that it can make your Blazor components more flexible and adaptable to different hosting models. For example, you can create a service that abstracts the data access logic for your components, and then register it with different implementations depending on whether you are using Blazor Server or Blazor WebAssembly. This way, you can reuse your components without changing their code. Another benefit is that it can make your Program.cs more concise and readable, as you can group related services into one extension method.
How to implement a service collection extension
AddOrderManagementServices.cs
public static class OrderManagementServiceExtensions
{
public static IServiceCollection AddOrderManagementServices(this IServiceCollection services)
{
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
return services;
}
}
Then, in your Blazor Server app’s Program.cs class, you can call the extension method
Program.cs
builder.Services.AddOrderManagementServices();
.
.
.
var app = builder.Build();
.
.
app.Run();
A lot more concise, huh?
Program.cs
By using this pattern, you can simplify and organize your service registration code, and enjoy the benefits of dependency injection in your Blazor Server applications.
Want to learn more?
In Memory State Management with Blazor Server
Creating your first In Memory State Container with Blazor Server Web technology has come along way in the relatively recent past. With the surge in popularity of SPAs and Javascript Frameworks a lot of developers…
Read moreHow to add HealthChecks to a ASP.net Core application
Adding HealthChecks to your application can drastically reduce troubleshooting time Why would you want to monitor your applications health? Health checks can test an applications dependencies, such as databases and external service endpoints, to confirm…
Read moreIHttpClientFactory vs. HttpClient
Why should you use IHttpClientFactory The main reason to use IHttpClientFactoryinstead of HttpClient directly is to manage the life cycle of HttpClient instances. HttpClient was designed to be instantiated once and reused throughout the application…
Read more