Как вы решаете проблему shared business logic между Xamarin и другими платформами (например, через .NET Standard, MAUI)?
Решение задачи повторного использования бизнес-логики между Xamarin и другими платформами — ключевой аспект построения кросс-платформенных решений. Важно структурировать проект таким образом, чтобы максимальная часть кода (модели, сервисы, бизнес-правила) могла быть переиспользована в других приложениях (например, .NET MAUI, WPF, ASP.NET Core или консольных утилитах), минимизируя дублирование и поддерживая единый источник правды.
.NET Standard как основа общего кода
До появления .NET 5/6 и MAUI, самым распространённым способом совместного использования бизнес-логики в Xamarin была библиотека на базе .NET Standard. Этот формат позволяет писать кросс-платформенные библиотеки, которые могут использоваться в проектах под iOS, Android, UWP, WPF, Blazor и другими .NET-ориентированными платформами.
Пример структуры проекта:
/MyApp.Solution
├── MyApp.Mobile (Xamarin.Forms UI)
├── MyApp.Web (ASP.NET Core)
├── MyApp.MAUI (MAUI UI)
├── MyApp.Shared (.NET Standard Library)
│ ├── Models/
│ ├── Services/
│ ├── Interfaces/
│ └── UseCases/
В .NET Standard библиотеке располагаются:
-
Модели данных (POCO): User, Product, Order и т.д.
-
Сервисы: например, IAuthService, IDataSyncService
-
Бизнес-логика / UseCase’ы: классы, реализующие логику (например, валидация заказа)
-
Интерфейсы и репозитории: используются для DI и абстрагирования от платформенной реализации
Преимущества .NET Standard:
-
Переиспользуемость на многих .NET-платформах.
-
Независимость от UI-фреймворков.
-
Совместимость с большинством популярных библиотек (JSON.NET, Polly и т.д.).
-
Простая интеграция в Xamarin, MAUI, WPF, Blazor.
Внедрение бизнес-логики в разные платформы
После вынесения логики в MyApp.Shared, она может быть внедрена через Dependency Injection или через сервис-локаторы:
Пример (в Xamarin.Forms):
public class LoginViewModel
{
private readonly IAuthService \_authService;
public LoginViewModel(IAuthService authService)
{
\_authService = authService;
}
public async Task LoginAsync(string username, string password)
{
var result = await \_authService.Login(username, password);
// дальнейшая логика
}
}
IAuthService — определён в .NET Standard, но его реализация может быть разной для платформ Xamarin, MAUI или Web.
Реализация сервисов через Dependency Injection
Внутри UI-проекта (Xamarin.Forms, MAUI и т.д.) подключается DI-контейнер и регистрируются зависимости:
builder.Services.AddSingleton<IAuthService, AuthService>();
Таким образом, бизнес-логика в .NET Standard обращается к IAuthService, не зная, как и где он реализован — это зависит от платформы.
Поддержка разных платформ: Xamarin, MAUI, Web
Если бизнес-логика изначально написана в .NET Standard, то она с минимальными изменениями может быть использована:
-
В Xamarin.Forms через Xamarin.Forms UI и DependencyService или DI.
-
В .NET MAUI без миграции, так как MAUI полностью поддерживает .NET Standard 2.0/2.1 и .NET 6/7.
-
В Blazor WebAssembly или Server — через DI и вызовы методов сервисов.
-
В WPF и WinForms — UI-слой работает с той же бизнес-логикой через ViewModel’и.
-
В ASP.NET Core — например, для админки или REST API, использующей ту же логику валидации.
В будущем: переход на .NET 6/7 и MAUI Class Libraries
С появлением .NET 6/7 и MAUI, Microsoft рекомендует использовать вместо .NET Standard — .NET SDK-style библиотеки, которые поддерживают multi-targeting:
<TargetFrameworks>net7.0;net7.0-ios;net7.0-android</TargetFrameworks>
Это позволяет:
-
Создавать библиотеки, которые включают платформо-специфические реализации.
-
Использовать #if ANDROID, #if IOS для разделения логики.
-
Всё ещё иметь общую бизнес-логику без зависимости от UI.
Подход через NuGet
Если планируется повторное использование логики в нескольких решениях, общий код можно вынести в NuGet-пакет:
-
Создаётся .NET Standard или .NET библиотека.
-
Собирается .nupkg и публикуется (в MyGet, Azure Artifacts, NuGet.org или GitHub Packages).
-
Подключается как зависимость во всех нужных приложениях.
Это позволяет централизованно обновлять бизнес-логику и синхронизировать изменения.
Примеры бизнес-логики, выносимой в общий код
-
Авторизация и управление токенами.
-
Работа с моделями данных (например, Order, Inventory).
-
Сервис работы с API (например, через HttpClient).
-
Операции с кэшем, валидацией, форматированием, вычислениями.
-
Использование общих Command, RelayCommand, ViewModelBase.
Ограничения и особенности
-
В .NET Standard нельзя использовать платформенно-зависимые API напрямую (например, Bluetooth, GPS, Push). Для них нужно использовать абстракции + DependencyService/DI.
-
UI-компоненты (XAML, Custom Renderers) нельзя вынести в общую библиотеку без MAUI или специфичного таргетинга.
-
Сложные зависимости (например, Camera API) требуют делегирования их в слой конкретной платформы (через интерфейсы).
-
При переходе с Xamarin на MAUI, Shared библиотека может использоваться без модификаций, если она на .NET Standard 2.0/2.1.
Пример внедрения бизнес-логики с DI
// Shared: IOrderService.cs
public interface IOrderService
{
Task<IEnumerable<Order>> GetOrdersAsync();
}
// Shared: OrderService.cs
public class OrderService : IOrderService
{
private readonly IApiClient \_client;
public OrderService(IApiClient client)
{
\_client = client;
}
public async Task<IEnumerable<Order>> GetOrdersAsync()
{
return await \_client.GetAsync<List<Order>>("api/orders");
}
}
Регистрация в Xamarin.Forms:
services.AddSingleton<IOrderService, OrderService>();
ViewModel использует IOrderService, а конкретная реализация настраивается в UI-проекте.
Итоговая структура кросс-платформенной архитектуры
-
Весь общий код — в MyApp.Core (.NET Standard или multi-targeted library).
-
Интерфейсы и бизнес-логика — в Core.
-
Реализации сервисов — в Platform/Presentation слоях (Xamarin, MAUI, Web).
-
UI взаимодействует только с Core через ViewModel, сервисы и DI.
Такой подход позволяет не просто делить код между Xamarin и другими платформами, а выстраивать устойчивую и масштабируемую архитектуру для любых будущих кросс-платформенных сценариев.