84 lines
3.4 KiB
C#
84 lines
3.4 KiB
C#
namespace BotPages.Core
|
||
{
|
||
/// <summary>
|
||
/// Базовая реализация реестра страниц на словаре.
|
||
/// </summary>
|
||
public sealed class PageRegistry : IPageRegistry
|
||
{
|
||
private readonly Dictionary<string, IPage> _pages = new(StringComparer.Ordinal);
|
||
private readonly IPage _defaultPage;
|
||
|
||
/// <summary>
|
||
/// Создаёт реестр из набора страниц.
|
||
/// </summary>
|
||
public PageRegistry(IEnumerable<IPage> pages) : this(pages, pages.First())
|
||
{
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создаёт реестр из набора страниц.
|
||
/// </summary>
|
||
public PageRegistry(IEnumerable<IPage> pages, IPage defaultPage)
|
||
{
|
||
foreach (var p in pages) _pages[p.Id] = p;
|
||
_defaultPage = defaultPage;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Возвращает страницу по идентификатору.
|
||
/// </summary>
|
||
public IPage Get(string id) => _pages[id];
|
||
|
||
/// <summary>
|
||
/// Возвращает страницу по идентификатору. Если страницы нет, возвращает дефолтную.
|
||
/// </summary>
|
||
public IPage GetOrDefault(string id)
|
||
=> _pages.TryGetValue(id, out var page) ? page : _defaultPage;
|
||
|
||
/// <summary>
|
||
/// Возвращает дефолтную страницу.
|
||
/// </summary>
|
||
public IPage DefaultPage => _defaultPage;
|
||
|
||
/// <summary>
|
||
/// Пытается получить страницу по идентификатору.
|
||
/// </summary>
|
||
public bool TryGet(string id, out IPage? page) => _pages.TryGetValue(id, out page);
|
||
|
||
/// <summary>
|
||
/// Возвращает все зарегистрированные страницы.
|
||
/// </summary>
|
||
public IEnumerable<IPage> All() => _pages.Values;
|
||
|
||
/// <summary>
|
||
/// Создаёт реестр страниц из всех сборок приложения.
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
}
|
||
} |