namespace Lattice.Core.Docking.Services; /// /// Реестр типов содержимого, который позволяет создавать экземпляры контента по типу. /// Этот сервис является центральным для динамического создания панелей инструментов и документов. /// /// /// Реализует шаблон "Фабрика" для создания экземпляров . /// Позволяет регистрировать фабричные методы для различных типов контента, что обеспечивает /// позднее связывание и возможность плагинной архитектуры. /// public class ContentRegistry { private readonly Dictionary _contentTypes = new(); /// /// Регистрирует фабричный метод для создания контента указанного типа. /// /// /// Тип контента, реализующий . /// /// Уникальный идентификатор типа контента. /// Фабричный метод для создания экземпляров контента. /// Метаданные типа контента (опционально). /// /// Выбрасывается, если или /// равны null. /// /// /// Выбрасывается, если уже зарегистрирован. /// public void Register(string contentTypeId, Func factory, ContentMetadata? metadata = null) where T : Abstractions.IDockContent { if (string.IsNullOrWhiteSpace(contentTypeId)) throw new ArgumentNullException(nameof(contentTypeId)); if (factory == null) throw new ArgumentNullException(nameof(factory)); // Дополнительная проверка на пустую строку if (string.IsNullOrEmpty(contentTypeId.Trim())) throw new ArgumentException("Идентификатор типа контента не может быть пустой строкой.", nameof(contentTypeId)); if (_contentTypes.ContainsKey(contentTypeId)) throw new ArgumentException($"Тип контента '{contentTypeId}' уже зарегистрирован."); _contentTypes[contentTypeId] = new ContentDescriptor( typeof(T), () => factory(), metadata ?? new ContentMetadata(contentTypeId, typeof(T).Name) ); } /// /// Создает новый экземпляр контента указанного типа с заданным идентификатором. /// /// Идентификатор типа контента. /// Уникальный идентификатор для создаваемого экземпляра контента. /// /// Новый экземпляр контента. /// /// /// Выбрасывается, если равен null или пустой строке. /// /// /// Выбрасывается, если тип контента не зарегистрирован. /// public Abstractions.IDockContent CreateContent(string contentTypeId, string id) { if (string.IsNullOrWhiteSpace(contentTypeId)) throw new ArgumentNullException(nameof(contentTypeId)); if (!_contentTypes.TryGetValue(contentTypeId, out var descriptor)) throw new KeyNotFoundException($"Тип контента '{contentTypeId}' не зарегистрирован."); var content = descriptor.Factory(); content.SetId(id); return content; } /// /// Получает метаданные для указанного типа контента. /// /// Идентификатор типа контента. /// /// Метаданные типа контента или null, если тип не найден. /// public ContentMetadata? GetMetadata(string contentTypeId) { if (string.IsNullOrWhiteSpace(contentTypeId)) return null; return _contentTypes.TryGetValue(contentTypeId, out var descriptor) ? descriptor.Metadata : null; } /// /// Получает все зарегистрированные типы контента. /// /// /// Коллекция идентификаторов зарегистрированных типов контента. /// public IEnumerable GetRegisteredTypes() => _contentTypes.Keys; /// /// Проверяет, зарегистрирован ли указанный тип контента. /// /// Идентификатор типа контента. /// /// true, если тип контента зарегистрирован; в противном случае false. /// public bool IsRegistered(string contentTypeId) { if (string.IsNullOrWhiteSpace(contentTypeId)) return false; return _contentTypes.ContainsKey(contentTypeId); } /// /// Представляет дескриптор типа контента, содержащий информацию о фабричном методе и метаданных. /// private class ContentDescriptor { /// /// Получает тип контента. /// public Type ContentType { get; } /// /// Получает фабричный метод для создания экземпляров контента. /// public Func Factory { get; } /// /// Получает метаданные типа контента. /// public ContentMetadata Metadata { get; } /// /// Инициализирует новый экземпляр класса . /// /// Тип контента. /// Фабричный метод. /// Метаданные. public ContentDescriptor(Type contentType, Func factory, ContentMetadata metadata) { ContentType = contentType; Factory = factory; Metadata = metadata; } } } /// /// Представляет метаданные типа контента, предоставляющие дополнительную информацию для отображения в UI. /// public class ContentMetadata { /// /// Получает идентификатор типа контента. /// /// /// Уникальный строковый идентификатор типа контента. /// public string ContentTypeId { get; } /// /// Получает или задает отображаемое имя типа контента. /// /// /// Имя типа контента, отображаемое пользователю. /// public string DisplayName { get; set; } /// /// Получает или задает описание типа контента. /// /// /// Текстовое описание функциональности контента. /// public string Description { get; set; } /// /// Получает или задает имя ресурса для иконки типа контента. /// /// /// Имя ресурса иконки или null, если иконка не определена. /// public string? IconResource { get; set; } /// /// Получает или задает значение, указывающее, является ли контент документом /// (а не инструментальной панелью). /// /// /// true, если контент является документом; в противном случае false. /// public bool IsDocument { get; set; } /// /// Получает или задает ширину контента по умолчанию. /// /// /// Ширина контента в пикселях. Значение по умолчанию: 300. /// public double DefaultWidth { get; set; } = 300; /// /// Получает или задает высоту контента по умолчанию. /// /// /// Высота контента в пикселях. Значение по умолчанию: 200. /// public double DefaultHeight { get; set; } = 200; /// /// Инициализирует новый экземпляр класса . /// /// Идентификатор типа контента. /// Отображаемое имя типа контента. /// /// Выбрасывается, если или /// равны null. /// public ContentMetadata(string contentTypeId, string displayName) { ContentTypeId = contentTypeId ?? throw new ArgumentNullException(nameof(contentTypeId)); DisplayName = displayName ?? throw new ArgumentNullException(nameof(displayName)); Description = string.Empty; } }