namespace BotPages.Core
{
///
/// Базовая реализация реестра страниц на словаре.
///
public sealed class PageRegistry : IPageRegistry
{
private readonly Dictionary _pages = new(StringComparer.Ordinal);
private readonly IPage _defaultPage;
///
/// Создаёт реестр из набора страниц.
///
public PageRegistry(IEnumerable pages) : this(pages, pages.First())
{
}
///
/// Создаёт реестр из набора страниц.
///
public PageRegistry(IEnumerable pages, IPage defaultPage)
{
foreach (var p in pages) _pages[p.Id] = p;
_defaultPage = defaultPage;
}
///
/// Возвращает страницу по идентификатору.
///
public IPage Get(string id) => _pages[id];
///
/// Возвращает страницу по идентификатору. Если страницы нет, возвращает дефолтную.
///
public IPage GetOrDefault(string id)
=> _pages.TryGetValue(id, out var page) ? page : _defaultPage;
///
/// Возвращает дефолтную страницу.
///
public IPage DefaultPage => _defaultPage;
///
/// Пытается получить страницу по идентификатору.
///
public bool TryGet(string id, out IPage? page) => _pages.TryGetValue(id, out page);
///
/// Возвращает все зарегистрированные страницы.
///
public IEnumerable All() => _pages.Values;
///
/// Создаёт реестр страниц из всех сборок приложения.
///
public static PageRegistry CreateFromApplication(string? defaultPageId = null)
{
// Берём все загруженные сборки в текущем AppDomain
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
// Находим все классы, реализующие IPage
var pages = assemblies
.SelectMany(a => a.GetTypes())
.Where(t => typeof(IPage).IsAssignableFrom(t) && !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null)
.Select(t => (IPage)Activator.CreateInstance(t)!)
.ToList();
if (pages.Count == 0)
throw new InvalidOperationException($"В приложении не найдено ни одной страницы ({nameof(IPage)}).");
// Определяем страницу по умолчанию
var defaultPage = defaultPageId != null
? pages.FirstOrDefault(p => p.Id == defaultPageId)
: pages.First();
if (defaultPage == null)
throw new InvalidOperationException($"Не найдена страница с Id={defaultPageId}.");
return new PageRegistry(pages, defaultPage);
}
}
}