using System; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; namespace HashCalculator.GUI { internal class Command : ICommand { private readonly Func _action; private readonly Action _onAsyncException; private bool _canExecute = true; public bool CanExecuteValue { get => _canExecute; set { _canExecute = value; CanExecuteChanged?.Invoke(this, new EventArgs()); } } public event EventHandler? CanExecuteChanged; public Command(Func action, Action? onAsyncException = null) { _action = action; _onAsyncException = onAsyncException ?? (exception => { MessageBox.Show($"Unhandled async exception in {nameof(Command)}: {exception}"); Application.Current.Shutdown(1); }); } public bool CanExecute(object? parameter) { return _canExecute; } public void Execute(object? parameter) { if (!_canExecute) { return; } if (!(parameter is T typed)) { throw new ArgumentException($"{nameof(parameter)} wrong type"); } ExecuteTaskInternal(ExecuteTask(typed)); } public Task ExecuteTask(T parameter) => _action(parameter); private async void ExecuteTaskInternal(Task task) { try { await task.ConfigureAwait(true); } catch (Exception exception) { _onAsyncException(exception); } } } internal class Command : ICommand { private readonly Func _action; private readonly Action _onAsyncException; private bool _canExecute = true; public bool CanExecuteValue { get => _canExecute; set { _canExecute = value; CanExecuteChanged?.Invoke(this, new EventArgs()); } } public event EventHandler? CanExecuteChanged; public Command(Func action, Action? onAsyncException = null) { _action = action; _onAsyncException = onAsyncException ?? (exception => { MessageBox.Show($"Unhandled async exception in {nameof(Command)}: {exception}"); Application.Current.Shutdown(1); }); } public bool CanExecute(object? parameter) { return _canExecute; } public void Execute(object? parameter) { if (!_canExecute) { return; } ExecuteTaskInternal(ExecuteTask()); } public Task ExecuteTask() => _action(); private async void ExecuteTaskInternal(Task task) { try { await task.ConfigureAwait(true); } catch (Exception exception) { _onAsyncException(exception); } } } }