using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; using Avalonia.Controls; using Avalonia.Controls.Templates; using GSS2.UI.Core.ViewModels; namespace GSS2; /// /// - интерфейс между Avalonia и механизмом DI (Dependency Injection) /// из Microsoft.Extensions.Hosting.
/// Создаёт View для переданной ViewModel.
/// Обязательным условием его работы является, то что: /// /// Класс View находится в пространстве имён SomeNameSpace.Views и имеет имя SomeClassView /// Класс ViewModel находится в пространстве имён SomeNameSpace.ViewModels и имеет имя SomeClassViewModel /// Класс ViewModel наследован от /// Класс View наследован от /// ///
public class DependencyInjectionViewLocator : IDataTemplate { private readonly ILogger _logger; private readonly IServiceProvider _services; public DependencyInjectionViewLocator(ILogger logger, IServiceProvider services) { _logger = logger; _services = services; } public bool Match(object? data) => data is ViewModelBase; public Control? Build(object? data) { // Если data - null или каким-то образом не ViewModelBase, то возвращаем null if (data is not ViewModelBase viewModel) return null; // Получаем имя класса ViewModel с полным описанием сборки var viewModelName = viewModel.GetType().AssemblyQualifiedName; if (viewModelName is null) { _logger.LogError("Не удалось получить имя класса ViewModel: {}", viewModel); return new Control(); } // Заменяем ".ViewModel" на ".View" в имени класса ViewModel и получаем имя класса View и его тип var viewName = viewModelName.Replace("ViewModel", "View"); var viewType = Type.GetType(viewName); if (viewType is null) { _logger.LogError("Не удалось найти класс View \"{}\"", viewName); return new Control(); } // Ищем тип View в сервисах var view = _services.GetService(viewType); if (view is null) { _logger.LogError("Класс View \"{}\" не зарегистрирован", viewName); return new Control(); } if (view is not Control control) { _logger.LogError("Класс View \"{}\" не наследован от Control", viewName); return new Control(); } control.DataContext = viewModel; return control; } }