using System; using System.Threading.Tasks; using System.Windows.Input; namespace JD.Guinness.WPF.Module { public sealed class AsyncDelegateCommand : ICommand { #region Fields private readonly Func _executeAsync; private readonly Func _canExecute; private volatile bool _isExecuting; #endregion #region Initialisation public AsyncDelegateCommand(Func executeAsync, Func canExecute) { _executeAsync = executeAsync ?? throw new ArgumentNullException(nameof(executeAsync)); _canExecute = canExecute; } public AsyncDelegateCommand(Func executeAsync) : this(executeAsync, null) { } #endregion #region Methods public bool CanExecute() => !_isExecuting && (_canExecute?.Invoke() ?? true); public async Task ExecuteAsync() { _isExecuting = true; await _executeAsync().ConfigureAwait(true); _isExecuting = false; } #endregion #region ICommand event EventHandler ICommand.CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } bool ICommand.CanExecute(object parameter) => CanExecute(); async void ICommand.Execute(object parameter) => await ExecuteAsync().ConfigureAwait(true); #endregion } public sealed class AsyncDelegateCommand : ICommand { #region Fields private readonly Func _executeAsync; private readonly Predicate _canExecute; private readonly bool _isClass; private volatile bool _isExecuting; #endregion #region Initialisation public AsyncDelegateCommand(Func executeAsync, Predicate canExecute) { _executeAsync = executeAsync ?? throw new ArgumentNullException(nameof(executeAsync)); _canExecute = canExecute; _isClass = typeof(T).IsClass; } public AsyncDelegateCommand(Func executeAsync) : this(executeAsync, null) { } #endregion #region Methods public bool CanExecute(T parameter) => !_isExecuting && (_canExecute?.Invoke(parameter) ?? true); public async Task ExecuteAsync(T parameter) { _isExecuting = true; await _executeAsync(parameter).ConfigureAwait(true); _isExecuting = false; } #endregion #region ICommand event EventHandler ICommand.CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } bool ICommand.CanExecute(object parameter) { if (!(parameter is T) || (parameter == null && !_isClass)) { return false; } return CanExecute((T)parameter); } async void ICommand.Execute(object parameter) => await ExecuteAsync((T)parameter).ConfigureAwait(true); #endregion } }