C# > Blazor and Web Development > Blazor Components > Dependency Injection in Blazor

Basic Dependency Injection in a Blazor Component

This snippet demonstrates basic dependency injection in a Blazor component. We inject a service (IMyService) into the component and use it to display a message.

Defining the Service Interface and Implementation

First, we define an interface IMyService that specifies the contract for our service. Then, we create a concrete implementation MyService that implements this interface and provides the actual logic (in this case, returning a message).

public interface IMyService
{
    string GetMessage();
}

public class MyService : IMyService
{
    public string GetMessage() => "Hello from MyService!";
}

Registering the Service in Startup.cs (or Program.cs in .NET 6+)

Next, we need to register our service with the dependency injection container. This is typically done in the ConfigureServices method of the Startup.cs file (or directly in Program.cs in .NET 6 and later). We use AddScoped which creates a new service instance for each scope. Usually, a Blazor component's lifespan is a scope. Other options are AddSingleton (creates a single instance for the entire application) and AddTransient (creates a new instance every time it's requested).

// In Program.cs (for .NET 6+)
builder.Services.AddScoped<IMyService, MyService>();

// In Startup.cs (for older .NET versions)
// public void ConfigureServices(IServiceCollection services)
// {
//     services.AddScoped<IMyService, MyService>();
// }

Injecting the Service into the Blazor Component

In the Blazor component, we use the @inject directive to inject the IMyService. The DI container will automatically provide an instance of MyService to the component. We can then access the service and its methods within the component's markup.

@page "/di"
@inject IMyService MyService

<h1>Dependency Injection Example</h1>

<p>Message: @MyService.GetMessage()</p>

Concepts Behind the Snippet

This snippet demonstrates the core concepts of Dependency Injection (DI). DI is a design pattern that promotes loose coupling between classes. Instead of a class creating its dependencies, those dependencies are injected into the class from the outside. This makes the class more testable, reusable, and maintainable.

Real-Life Use Case

A common use case for DI is injecting a data access service into a Blazor component. The data access service could be responsible for fetching data from a database or an API. By injecting the service, the component doesn't need to know the details of how the data is retrieved, it only needs to know how to use the service.

Best Practices

  • Always program to interfaces, not concrete implementations. This allows you to easily switch out implementations without modifying the code that uses the interface.
  • Use constructor injection whenever possible. This makes it clear what dependencies a class has.
  • Consider the lifetime of your services (Singleton, Scoped, or Transient) and choose the appropriate lifetime for your needs.

When to Use Them

Use dependency injection when you want to decouple your components from their dependencies. This makes your code more testable, maintainable, and reusable. DI is especially useful in large applications with many components.

Pros

  • Improved Testability: Easier to unit test components because dependencies can be mocked or stubbed.
  • Increased Reusability: Components are less tightly coupled and can be reused in different contexts.
  • Enhanced Maintainability: Easier to modify or replace dependencies without affecting other parts of the application.

Cons

  • Increased Complexity: Can add complexity to smaller projects.
  • Potential Performance Overhead: Can introduce a small performance overhead due to the DI container resolving dependencies.

FAQ

  • What is the difference between AddSingleton, AddScoped, and AddTransient?

    AddSingleton creates a single instance of the service that is shared across the entire application. AddScoped creates a new instance of the service for each scope (typically, each user session or HTTP request). AddTransient creates a new instance of the service every time it is requested.
  • Can I use constructor injection in Blazor components?

    While technically possible with some workarounds (custom component factories), @inject is the recommended and most straightforward way to inject dependencies into Blazor components.