Внедрение зависимостей в компоненты Blazor

Последнее обновление: 30.11.2023

Фреймворк Blazor позволяет воспользоваться систмой внедрения зависимостей, которая используется в ASP.NET Core и в целом в .NET. Рассомтрим только те моменты механизма DI, которые характерны именно для приложения Blazor. Пусть у нас есть следующий проект с одним компонентом App.razor и файлом TimeService.cs

Внедрение зависимостей в компоненты Blazor в C#

В файле TimeService.cs определен одноименный сервис:

public interface ITimeService
{
    string GetTime();
}
public class TimeService : ITimeService
{
    public string GetTime() => DateTime.Now.ToShortTimeString();
}

Класс TimeService представляет интерфейс ITimeService и реализует его метод GetTime(), который возвращает текущее время.

В главном файле программы - Program.cs добавим сервис ITimeService в коллекцию сервисов приложения:

using BlazorApp.Components;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// добавляем сервис TimeService
builder.Services.AddTransient<ITimeService, TimeService>();

var app = builder.Build();

app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

Для установки сервисов через свойство Services получаем коллекцию сервисов приложения - объект IServiceCollection. Далее у него вызываем методы AddTransient/AddScoped/AddSingleton для добавления сервиса. В данном случае посредством метода AddTransient добавляем для сервиса ITimeService в качестве реализации класс TimeService.

Для получения сервиса в компоненте применяется директива @inject. Например, получим сервис ITimeService в компоненте App:

@page "/"
@inject ITimeService Timer

<!DOCTYPE html>
<html>
<head>
    <title>METANIT.COM</title>
    <meta charset="utf-8" />
</head>
<body>
    <h2>Time: @Timer.GetTime()</h2>
    <script src="_framework/blazor.web.js"></script>
</body>
</html>

После директивы @inject указывается название сервиса (ITimeService), а затем название переменной (Timer), через которую можно получить реализацию сервиса.

@inject ITimeService Timer

Используя название переменной, можно обращаться к функциональности сервиса в коде компонента:

<h2>Time: @Timer.GetTime()</h2>

В итоге после запуска проекта на веб-странице в заголовке мы увидим текущее время, которое получено через сервис ITimeService:

Получение сервисов в компонентах Blazor на C#

Атрибут [Inject]

Для получения сервисов в компоненте также можно использовать атрибут [Inject]. Этот атрибут применяется к свойству, в которое получаем сервис. Например, изменим компонент App следующим образом:

@page "/"

<!DOCTYPE html>
<html>
<head>
    <title>METANIT.COM</title>
    <meta charset="utf-8" />
</head>
<body>
    <h2>Time: @Timer.GetTime()</h2>
    <script src="_framework/blazor.web.js"></script>
</body>
</html>

@code {

    [Inject]
    public required ITimeService Timer { get; set; }
}

Поскольку к свойству Timer применяется атрибут [Inject], то значение для данного свойства будет обеспечивать система внедрения зависимостей. Поскольку это свойство представляет ITimeService, то механиз DI будет искать в коллекции сервисов реализацию именно этого типа.

Получение сервисов в других сервисах

Если сервис предполагается использовать в другом сервисе, то один сервис может получить другой, как и вобще в .NET, через конструктор. Например, пусть у нас есть еще один сервис -

public class TimeFormatter
{
    ITimeService timeService;
    public TimeFormatter(ITimeService timeService)
    {
        this.timeService = timeService;
    }
    public string FormatTime() => $"Current Time: {timeService.GetTime()}";
}

Он использует сервис ITimeService, который он получает через механизм DI через параметр конструктора.

В файле Program.cs оба сервиса добавляются в коллекцию сервисов приложения:

using BlazorApp.Components;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// добавляем сервисы
builder.Services.AddTransient<ITimeService, TimeService>();
builder.Services.AddTransient<TimeFormatter>();

var app = builder.Build();

app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

В компоненте App также получим сервис TimeFormatter для рендеринга содержимого:

@page "/"
@inject TimeFormatter Formatter

<!DOCTYPE html>
<html>
<head>
    <title>METANIT.COM</title>
    <meta charset="utf-8" />
</head>
<body>
    <h2>@Formatter.FormatTime()</h2>
    <script src="_framework/blazor.web.js"></script>
</body>
</html>
Получение сервисов в других сервисах в приложении Blazor на C#

Сервисы по умолчанию

Ряд сервисов фреймворк Blazor предоставляет по умолчанию. Например, выведем все сервисы на консоль в файле Program.cs:

using BlazorApp.Components;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// добавляем сервисы
builder.Services.AddTransient<ITimeService, TimeService>();
builder.Services.AddTransient<TimeFormatter>();

// выводим все сервисы на консоль
foreach (var service in builder.Services)
{
    Console.WriteLine(service.ServiceType);
}

var app = builder.Build();

app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

Сервисы по умолчанию в приложении Blazor на C#
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850