Мы рассмотрим, когда полезно использовать код программной части при разработке Blazor, какие преимущества мы получим и чего ожидать при повторном факторинге существующих компонентов.

При работе с Blazor в архитектуре компонентов по умолчанию вся разметка и логика смешиваются в одном файле (.razor). Когда компоненты просты, этот подход работает хорошо, однако по мере усложнения управления всем компонентом в целом становится все труднее. Использование подхода «код программной части» позволяет разделить разметку и логику в отдельные файлы. В этой статье мы рассмотрим, когда полезно использовать код программной части, какие преимущества мы получаем и чего ожидать при повторном факторинге существующих компонентов.

Однофайловый подход

Начнем с краткого обзора подхода, основанного на использовании одного файла. В качестве примера мы будем использовать компонент FetchData в шаблоне ASP.NET по умолчанию. Компонент FetchData отображает HTML-таблицу данных прогноза погоды путем перебора данных, предоставленных службой. Компонент использует директивы, HTML / Razor и блок @code; все это типичные элементы, составляющие компонент.

Разметка для компонента довольно подробная. При весе более 30 строк разметка сама увеличивает длину файла, заставляя нас прокручивать вниз, чтобы найти логику компонентов, представленную блоком @code.

Имейте в виду, что этот компонент на самом деле довольно прост. По мере увеличения сложности каждый раздел будет расти. Это означает, что в конечном итоге у нас будет больше директив с использованием операторов, разметки и логики в нашем блоке кода. Хотя может быть удобно иметь всеобъемлющий файл, в конечном итоге его будет утомительно поддерживать из-за постоянной прокрутки между разметкой и логикой.

Давайте повторно проанализируем компонент FetchData с помощью файла кода программной части и посмотрим, как он улучшает общий опыт разработчика.

Подход с программным кодом

Код программной части - это общий термин для техники использования отдельного файла кода, который представляет всю логику для соответствующей страницы, представления или компонента. Для создания кода программной части в Blazor требуется несколько шагов, но, к счастью, он поддерживается фреймворком, поэтому настройка довольно проста. Чтобы завершить наш код программной части, нам нужно будет создать класс, а затем связать код программной части с нашей разметкой. Когда у нас есть структура, мы можем перейти к существующей логике.

Сначала нам понадобится файл класса, который будет представлять наш код программной части. Это стандартный класс .NET, но очень важно именование. Когда мы создаем наш файл кода программной части, нам необходимо учитывать как имя файла, так и имя класса, поскольку они могут значительно повлиять на наш опыт разработчика.

Начнем с имени файла. Когда мы добавляем имя файла, мы должны следовать общему соглашению [componentName]Base.razor.cs. Расширение .razor.cs понимается Visual Studio и будет правильно вложено в окно проводника файлов. Поскольку компонент уже занимает имя класса, нам нужно добавить суффикс Base к имени нашего класса, придав ему уникальное имя класса. Окончательный файл кода программной части должен быть FetchData.razor.cs с именем класса FetchDataBase.

Затем нам нужно связать разметку компонента (.razor) с выделенным кодом (.razor.cs). В файле кода программной части мы наследуем от ComponentBase. При наследовании от ComponentBase в Visual Studio сочетание клавиш ctrl + . добавит оператор using using Microsoft.AspNetCore.Components;, который является пространством имен для ComponentBase. На момент написания сочетание клавиш ctrl + . недоступно в Razor, как и многие инструменты рефакторинга для Visual Studio. Доступ к этим ярлыкам подчеркивает важность файлов кода программной части в Blazor.

using Microsoft.AspNetCore.Components;

namespace MyApp.Pages
{
    public class FetchDataBase : ComponentBase
    {
    }
}

Мы будем использовать аналогичный процесс в нашем файле разметки, чтобы установить связь между обоими файлами. В верхней части разметки компонента мы наследуем от нашего кода программной части с помощью директивы @inherits. Наследование от FetchDataBase формирует законченный компонент, и нам больше не нужно использовать блок @code для определения логики нашего компонента.

@inherits FetchDataBase
@page "/fetchdata"
@using WebApplication33.Data
@inject WeatherForecastService ForecastService

...markup

@code { ... }

Теперь мы можем перенести весь код из блока @code в наш код программной части, а также несколько директив.

Перенос @code в Code-Behind

Большая часть логики из нашего блока @code может быть скопирована напрямую как есть в код программной части без изменений, однако есть некоторые небольшие обновления, которые необходимо будет сделать. Блок @code привязан к классу компонента, в то время как область кода программной части является базовым классом компонента. Все, на что мы хотим ссылаться в базовом классе через разметку, должно быть помечено protected. В случае FetchData переменная forecasts используется в разметке компонентов, поэтому она должна быть защищена или общедоступна, чтобы быть видимой для класса FetchData. В коде программной части WeatherForecast[] forecasts; становится protected WeatherForecast[] forecasts;.

public class FetchDataBase : ComponentBase
    {
        protected WeatherForecast[] forecasts;

        ...
    }

Когда мы перемещаем код в наш код программной части, потребуются дополнительные операторы using, так как код программной части не использует глобальные значения в _Imports.razor. Здесь снова пригодятся стандартные инструменты: ctrl + . быстро устраняют любые отсутствующие пространства имен.

using Microsoft.AspNetCore.Components;
using System.Threading.Tasks; // Added by ctrl + .
using MyApp.Data; // Added by ctrl + .

namespace MyApp.Pages
{
    public class FetchDataBase : ComponentBase
    {
        protected WeatherForecast[] forecasts;

        protected override async Task OnInitAsync()
        {
            forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
        }
    }
}

После переноса всего кода нам все еще нужно выполнить один последний шаг - внедрение зависимостей (DI).

Внедрение зависимостей в программном обеспечении Blazor

Внедрение зависимостей в разметке Razor обрабатывается директивой @inject. Хотя директива доступна в классах кода программной части, она написана по-другому и на первый взгляд может быть неочевидной. Чтобы использовать внедрение зависимостей в файле кода программной части, мы будем использовать атрибут [Inject] и применим его к свойству того типа, который мы хотели бы внедрить, например: [Inject] MyType MyProp { get; set; }.

using Microsoft.AspNetCore.Components;
using System;
using System.Threading.Tasks;
using MyApp.Data;

namespace MyApp.Pages
{
    public class FetchDataBase : ComponentBase
    {
        [Inject] WeatherForecastService ForecastService { get; set; }

        protected WeatherForecast[] forecasts;      

        protected override async Task OnInitAsync()
        {
            forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
        }
    }
}

С добавленным атрибутом [Inject] компонент теперь может разрешить службу, и нам больше не нужна директива в разметке Razor. Мы можем продолжить очистку нашей разметки, удалив директивы @inject и @using, а также блок @code.

Заключительные мысли Code-Behind

Когда мы запускали компонент, все директивы, разметка и логика содержались в одном файле. Хотя подход с использованием одного файла дает преимущества в своей простоте и отлично подходит для небольших компонентов, он просто плохо масштабируется. Если нашему компоненту требуется сложная разметка или логика, легко потеряться в большом файле и / или запутаться в двух разных способах выражения кода. Кроме того, мы теряем доступ к некоторым из наиболее ценных инструментов Visual Studio для повышения производительности.

Процесс преобразования существующего компонента для использования кода программной части довольно прост. Требуется несколько изменений кода в отношении using операторов, уровней защиты и внедрения зависимостей. По большей части Visual Studio даже помогает нам внести необходимые исправления для достижения успешной компиляции.

Когда переход завершен, мы получаем выгоду от четко определенных ролей для разметки и логики с гораздо меньшей прокруткой. Если нам нужно увидеть компонент целиком, мы можем теперь привязать два окна бок о бок и сосредоточиться на текущей задаче.

Впервые на Blazor?

Если вы новичок в Blazor и хотите быстро начать обучение, просмотрите серию бесплатных видеороликов по быстрому запуску Blazor. В этой серии обучающих видео мы узнаем об ASP.NET Core Blazor. Изучите основы работы с такими понятиями Blazor: компоненты, события, привязка данных и многое другое. Курс ведет я, Эд Шарбено, отраслевой профессионал, четырехкратный MVP Microsoft.

Эта история изначально появилась в блоге Прогресс Телерик Эда Шарбено. Хотите узнать больше о технологиях и создании бизнес-приложений завтрашнего дня? Загляните в блог, чтобы узнать больше.