Skip to content

Commit d20586f

Browse files
committed
Add cancel implementation for async commands.
1 parent ae5c00f commit d20586f

File tree

10 files changed

+164
-4
lines changed

10 files changed

+164
-4
lines changed

src/UnityMvvmToolkit.Core/BaseCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ protected BaseCommand(Func<bool> canExecute)
1414
_canExecute = canExecute;
1515
}
1616

17-
public event EventHandler<bool> CanExecuteChanged;
17+
public virtual event EventHandler<bool> CanExecuteChanged;
1818

1919
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2020
public void RaiseCanExecuteChanged()

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/Core/BaseCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ protected BaseCommand(Func<bool> canExecute)
1414
_canExecute = canExecute;
1515
}
1616

17-
public event EventHandler<bool> CanExecuteChanged;
17+
public virtual event EventHandler<bool> CanExecuteChanged;
1818

1919
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2020
public void RaiseCanExecuteChanged()

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/External/UniTask/BaseAsyncCommand.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ protected BaseAsyncCommand(Func<bool> canExecute) : base(canExecute)
1515
{
1616
}
1717

18-
public bool DisableOnExecution { get; set; }
19-
2018
public virtual bool IsRunning
2119
{
2220
get => _isRunning;
@@ -27,6 +25,8 @@ protected set
2725
}
2826
}
2927

28+
public virtual bool DisableOnExecution { get; set; }
29+
3030
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3131
public override bool CanExecute()
3232
{
@@ -37,6 +37,10 @@ public override bool CanExecute()
3737

3838
return IsRunning == false && base.CanExecute();
3939
}
40+
41+
public virtual void Cancel()
42+
{
43+
}
4044
}
4145
}
4246

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/External/UniTask/Extensions.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#if UNITYMVVMTOOLKIT_UNITASK_SUPPORT
2+
3+
namespace UnityMvvmToolkit.UniTask.Extensions
4+
{
5+
using System;
6+
using Internal;
7+
using Interfaces;
8+
9+
public static class AsyncCommandExtensions
10+
{
11+
public static IAsyncCommand CreateCancelCommand(this IAsyncCommand asyncCommand)
12+
{
13+
if (asyncCommand == null)
14+
{
15+
throw new NullReferenceException(nameof(asyncCommand));
16+
}
17+
18+
return new AsyncCommandWithCancellation(asyncCommand);
19+
}
20+
21+
public static IAsyncCommand<T> CreateCancelCommand<T>(this IAsyncCommand<T> asyncCommand)
22+
{
23+
if (asyncCommand == null)
24+
{
25+
throw new NullReferenceException(nameof(asyncCommand));
26+
}
27+
28+
return new AsyncCommandWithCancellation<T>(asyncCommand);
29+
}
30+
}
31+
}
32+
33+
#endif

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/External/UniTask/Extensions/AsyncCommandExtensions.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/External/UniTask/Interfaces/IBaseAsyncCommand.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ public interface IBaseAsyncCommand
66
{
77
bool IsRunning { get; }
88
bool DisableOnExecution { get; set; }
9+
10+
void Cancel();
911
}
1012
}
1113

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/External/UniTask/Internal.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#if UNITYMVVMTOOLKIT_UNITASK_SUPPORT
2+
3+
namespace UnityMvvmToolkit.UniTask.Internal
4+
{
5+
using System;
6+
using Interfaces;
7+
using System.Threading;
8+
using Cysharp.Threading.Tasks;
9+
10+
internal class AsyncCommandWithCancellation : BaseAsyncCommand, IAsyncCommand
11+
{
12+
private readonly IAsyncCommand _asyncCommand;
13+
private CancellationTokenSource _cancellationTokenSource;
14+
15+
public AsyncCommandWithCancellation(IAsyncCommand asyncCommand) : base(null)
16+
{
17+
_asyncCommand = asyncCommand;
18+
}
19+
20+
public override bool DisableOnExecution
21+
{
22+
get => _asyncCommand.DisableOnExecution;
23+
set => _asyncCommand.DisableOnExecution = value;
24+
}
25+
26+
public override event EventHandler<bool> CanExecuteChanged
27+
{
28+
add => _asyncCommand.CanExecuteChanged += value;
29+
remove => _asyncCommand.CanExecuteChanged -= value;
30+
}
31+
32+
public void Execute()
33+
{
34+
ExecuteAsync().Forget();
35+
}
36+
37+
public async UniTask ExecuteAsync(CancellationToken cancellationToken = default)
38+
{
39+
_cancellationTokenSource?.Cancel();
40+
_cancellationTokenSource = new CancellationTokenSource();
41+
42+
try
43+
{
44+
await _asyncCommand.ExecuteAsync(_cancellationTokenSource.Token);
45+
}
46+
finally
47+
{
48+
_cancellationTokenSource?.Dispose();
49+
_cancellationTokenSource = null;
50+
}
51+
}
52+
53+
public override void Cancel()
54+
{
55+
_cancellationTokenSource?.Cancel();
56+
}
57+
}
58+
59+
internal class AsyncCommandWithCancellation<T> : BaseAsyncCommand, IAsyncCommand<T>
60+
{
61+
private readonly IAsyncCommand<T> _asyncCommand;
62+
private CancellationTokenSource _cancellationTokenSource;
63+
64+
public AsyncCommandWithCancellation(IAsyncCommand<T> asyncCommand) : base(null)
65+
{
66+
_asyncCommand = asyncCommand;
67+
}
68+
69+
public override bool DisableOnExecution
70+
{
71+
get => _asyncCommand.DisableOnExecution;
72+
set => _asyncCommand.DisableOnExecution = value;
73+
}
74+
75+
public override event EventHandler<bool> CanExecuteChanged
76+
{
77+
add => _asyncCommand.CanExecuteChanged += value;
78+
remove => _asyncCommand.CanExecuteChanged -= value;
79+
}
80+
81+
public void Execute(T parameter)
82+
{
83+
ExecuteAsync(parameter).Forget();
84+
}
85+
86+
public async UniTask ExecuteAsync(T parameter, CancellationToken cancellationToken = default)
87+
{
88+
_cancellationTokenSource?.Cancel();
89+
_cancellationTokenSource = new CancellationTokenSource();
90+
91+
try
92+
{
93+
await _asyncCommand.ExecuteAsync(parameter, _cancellationTokenSource.Token);
94+
}
95+
finally
96+
{
97+
_cancellationTokenSource?.Dispose();
98+
_cancellationTokenSource = null;
99+
}
100+
}
101+
102+
public override void Cancel()
103+
{
104+
_cancellationTokenSource?.Cancel();
105+
}
106+
}
107+
}
108+
109+
#endif

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/External/UniTask/Internal/AsyncCommandWithCancellation.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)