Доработан обработчик команд. Добавлена публикация команд
All checks were successful
CI / build-test (push) Successful in 31s
Release / pack-and-publish (release) Successful in 35s

This commit is contained in:
2025-12-07 10:09:59 +03:00
parent 8af03fa52b
commit edc718b1f9
9 changed files with 127 additions and 17 deletions

View File

@@ -2,30 +2,40 @@
using System.Text.RegularExpressions;
/// <summary>
/// Реестр команд, доступных из любого места.
/// </summary>
internal sealed class CommandsRegistry
{
private readonly List<(Regex pattern, Func<PageContext, CancellationToken, Task> handler)> _commands = new();
private readonly List<Command> _commands = new();
public List<Command> Commands => _commands;
/// <summary>
/// Зарегистрировать команду, ведущую на страницу.
/// </summary>
public CommandsRegistry Map<TPage>(string commandTemplate) where TPage : Page
public CommandsRegistry Map<TPage>(string commandTemplate, bool publish = false, string? description = null) where TPage : Page
{
var pattern = ToRegex(commandTemplate);
_commands.Add((pattern, (ctx, ct) => ctx.Navigation.GoToAsync<TPage>(ctx, ct)));
return this;
return Map(commandTemplate, (ctx, args, ct) => ctx.Navigation.GoToAsync<TPage>(ctx, ct), publish, description);
}
/// <summary>
/// Зарегистрировать команду с кастомным обработчиком.
/// </summary>
public CommandsRegistry Map(string commandTemplate, Func<PageContext, CancellationToken, Task> handler)
public CommandsRegistry Map(string commandTemplate, CommandHandler handler, bool publish = false, string? description = null)
{
var pattern = ToRegex(commandTemplate);
_commands.Add((pattern, handler));
_commands.Add(new Command()
{
Name = ToCommandName(commandTemplate),
Pattern = pattern,
Handler = handler,
Publish = publish,
Description = string.IsNullOrWhiteSpace(description) ? null : description
});
return this;
}
@@ -34,11 +44,19 @@ internal sealed class CommandsRegistry
/// </summary>
public bool TryDispatch(PageContext ctx, string command, CancellationToken ct, out Task? task)
{
foreach (var (pattern, handler) in _commands)
foreach (var cmd in _commands)
{
if (pattern.IsMatch(command))
var match = cmd.Pattern.Match(command);
if (match.Success)
{
task = handler(ctx, ct);
// Собираем аргументы
var args = cmd.Pattern.GetGroupNames()
.Where(n => n != "0")
.Select(n => new { n, v = match.Groups[n].Value })
.Where(x => !string.IsNullOrEmpty(x.v))
.ToDictionary(x => x.n, x => x.v);
task = cmd.Handler(ctx, args, ct);
return true;
}
}
@@ -56,4 +74,10 @@ internal sealed class CommandsRegistry
.Replace("{id?}", "(?<id>\\S+)?") + "$";
return new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
private static string ToCommandName(string template)
{
// Простейшее преобразование шаблона: "/open {page} {id?}" -> "/open"
return template.Split(" ", StringSplitOptions.RemoveEmptyEntries).First().ToLowerInvariant();
}
}