// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; using System.Collections.Generic; using System.Text.Json; namespace autoShell.Handlers; /// /// Base class for all action handlers. Co-registers action names and handler functions /// via or , providing automatic /// and dictionary-based dispatch. /// Subclasses register actions in their constructor. /// internal abstract class ActionHandlerBase : IActionHandler { private static readonly JsonSerializerOptions CamelCaseOptions = new() { PropertyNameCaseInsensitive = true }; private readonly Dictionary> _actions = new(StringComparer.OrdinalIgnoreCase); /// public IEnumerable SupportedActions => _actions.Keys; /// /// Registers an action name and its handler function. Throws if the name is already registered. /// protected void AddAction(string actionName, Func handler) { if (!_actions.TryAdd(actionName, handler)) { throw new InvalidOperationException( $"Action '{actionName}' is already registered in {GetType().Name}."); } } /// /// Registers an action with a strongly-typed parameter record. /// The is automatically deserialized to . /// protected void AddAction(string actionName, Func handler) { AddAction(actionName, parameters => { T typed; try { if (parameters.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) { return ActionResult.Fail($"Invalid parameters for '{actionName}': parameters are missing or null"); } typed = JsonSerializer.Deserialize(parameters.GetRawText(), CamelCaseOptions); } catch (JsonException ex) { return ActionResult.Fail($"Invalid parameters for '{actionName}': {ex.Message}"); } return typed == null ? ActionResult.Fail($"Invalid parameters for '{actionName}': null parameters not allowed") : handler(typed); }); } /// public virtual ActionResult Handle(string key, JsonElement parameters) { return _actions.TryGetValue(key, out var handler) ? handler(parameters) : ActionResult.Fail($"Unknown action: {key}"); } }