Доработан обработчик команд. Добавлена публикация команд
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user