JD2022-TU1/main/tools/modules/JD.Guinness.WPF.Module/AsyncDelegateCommand.cs

127 lines
3.2 KiB
C#

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<Task> _executeAsync;
private readonly Func<bool> _canExecute;
private volatile bool _isExecuting;
#endregion
#region Initialisation
public AsyncDelegateCommand(Func<Task> executeAsync, Func<bool> canExecute)
{
_executeAsync = executeAsync ?? throw new ArgumentNullException(nameof(executeAsync));
_canExecute = canExecute;
}
public AsyncDelegateCommand(Func<Task> 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<T> : ICommand
{
#region Fields
private readonly Func<T, Task> _executeAsync;
private readonly Predicate<T> _canExecute;
private readonly bool _isClass;
private volatile bool _isExecuting;
#endregion
#region Initialisation
public AsyncDelegateCommand(Func<T, Task> executeAsync, Predicate<T> canExecute)
{
_executeAsync = executeAsync ?? throw new ArgumentNullException(nameof(executeAsync));
_canExecute = canExecute;
_isClass = typeof(T).IsClass;
}
public AsyncDelegateCommand(Func<T, Task> 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
}
}