Расскажите про ваш опыт миграции Xamarin-приложений на .NET MAUI.
Миграция Xamarin-приложения на .NET MAUI (Multi-platform App UI) представляет собой стратегический и технический процесс, который требует глубокой подготовки, понимания архитектуры приложения и особенностей новых технологий. MAUI — это эволюция Xamarin.Forms, построенная на .NET 6/7/8, с целью унификации и упрощения кроссплатформенной разработки для Android, iOS, Windows и macOS.
Ниже подробно описан реальный опыт миграции большого корпоративного Xamarin.Forms-приложения на .NET MAUI, включая этапы, трудности и решения.
1. Предварительный аудит Xamarin-проекта
Перед началом миграции была проведена полная инвентаризация проекта:
-
Проверка версии Xamarin.Forms и зависимостей NuGet.
-
Анализ используемых платформенных API через DependencyService.
-
Поиск кастомных рендереров, эффектов, behavior'ов.
-
Выделение UI-слоя, бизнес-логики, сервисов, моделей.
-
Проверка unit-тестов и UI-тестов (на NUnit + Xamarin.UITest).
Также были оценены критические точки, не поддерживаемые напрямую в MAUI, например:
-
Custom Renderers → Handlers
-
MessagingCenter → EventAggregator или CommunityToolkit.MVVM
-
ResourceDictionary → пересмотр структуры
-
Shell-архитектура → изменения в навигации
2. Обновление к .NET 6/.NET 7 и MAUI workload
На этом этапе была подготовлена среда:
-
Установлены:
-
.NET SDK 6, 7 и 8
-
dotnet workload install maui
-
Visual Studio 2022/2023 с MAUI workload
-
-
Проект переведён на однофайловую .csproj-структуру
-
Создана новая MAUI-заготовка с типом dotnet new maui
3. Миграция общих библиотек
Бизнес-логика, модели и сервисы уже были размещены в .NET Standard 2.0 библиотеке. Для совместимости с MAUI она была:
-
Переведена в net6.0 или netstandard2.1
-
Пересобрана без изменений — основная логика не требует переписывания
-
Тесты также были переведены на xUnit с net6.0
Этап прошёл практически безболезненно благодаря слабой связности с UI.
4. Перенос UI-слоя
А. Разметка XAML
-
Поддержка XAML в MAUI сохраняется, однако:
-
Устаревшие свойства были удалены (Device.RuntimePlatform)
-
Были заменены OnPlatform, OnIdiom на DeviceInfo и AppThemeBinding
-
Импорты XMLNS переопределены под Microsoft.Maui.Controls
-
Б. Code-behind
-
Подключение событий, команд и BindingContext осталось аналогичным.
-
Требовалось заменить платформенные вызовы, особенно Android/Java API.
В. Shell
-
Структура навигации Shell практически полностью переносима.
-
Однако Routing.RegisterRoute() и URI-навигация требовали пересмотра.
-
Добавлены новые возможности FlyoutItem, TabBar, ShellContent.
5. Custom Renderers → Handlers
Одной из самых сложных частей стало переписывание Custom Renderer'ов.
-
В MAUI вместо Renderer используется Handler + Mapper API.
-
Пример перехода:
// В Xamarin
\[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))\]
// В MAUI
public class MyEntryHandler : EntryHandler
{
public MyEntryHandler() : base(Mapper)
{
}
public static IPropertyMapper<Entry, MyEntryHandler> Mapper =
new PropertyMapper<Entry, MyEntryHandler>(EntryHandler.Mapper)
{
\[nameof(MyEntry.BorderColor)\] = MapBorderColor
};
static void MapBorderColor(IEntryHandler handler, Entry entry)
{
// Платформенно-специфичная логика
}
}
- Требовалась миграция платформозависимых директорий (Platforms/Android, Platforms/iOS и т.д.)
6. DependencyService → Dependency Injection
MAUI использует встроенный DI через Microsoft.Extensions.DependencyInjection.
- В Program.cs регистрировались сервисы:
builder.Services.AddSingleton<IMyService, MyService>();
- Устаревшие вызовы DependencyService.Get<IMyService>() были заменены на DI-инъекции через конструктор:
public class MainViewModel
{
private readonly IMyService \_service;
public MainViewModel(IMyService service)
{
\_service = service;
}
}
7. Платформенный код
Многие платформенные зависимости, ранее реализованные через DependencyService и MainActivity.cs/AppDelegate.cs, были перенесены в соответствующие каталоги:
-
Platforms/Android/MainActivity.cs
-
Platforms/iOS/AppDelegate.cs
Для MAUI предусмотрены partial-классы, которые объединяются во время компиляции.
8. Использование MAUI Community Toolkit
Для компенсации недостающих функций Xamarin.Forms были добавлены:
-
CommunityToolkit.Maui:
-
Behaviors
-
Converters
-
SnackBar, Toast
-
ObservableObject / RelayCommand
-
Установка:
dotnet add package CommunityToolkit.Maui
И регистрация в Program.cs:
builder.UseMauiCommunityToolkit();
9. Тестирование и отладка
-
Основной фокус сделан на юнит-тестах: они работали без изменений.
-
UI-тесты были адаптированы к новым деревьям элементов.
-
Использовались:
-
Visual Studio MAUI Hot Reload
-
MAUI Previewer
-
Debug Proxies for ViewModels
-
10. Интеграция CI/CD
CI/CD пайплайны для GitHub Actions и Azure DevOps были обновлены:
-
Добавлены команды:
-
dotnet workload install maui
-
dotnet build -f net7.0-ios
-
dotnet build -f net7.0-android
-
-
Подключены новые ключи для .keystore и .p12
-
Переписаны публикационные шаги через fastlane
11. Итоговая архитектура после миграции
-
Переход на MVVM Toolkit вместо стороннего MVVM-фреймворка
-
Использование Shell + DI + Handlers
-
Single Project модель с платформенными папками
-
Unified ресурсные файлы (Resources/Images, Resources/Styles, Resources/Raw)
Миграция показала, что проект с чистой архитектурой, модульной логикой и слабой зависимостью от UI легко адаптируется под .NET MAUI. Однако наличие большого количества кастомных решений (рендереров, эффектов, платформенных вызовов) требует дополнительного времени и проектирования. Эффективный переход требует пошагового подхода, разбивки миграции на фазы и тщательного тестирования.