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;
}
}