Skip to content

Commit

Permalink
Fix to handle Cancellation Token Tasks for ReactiveCommand.CreateFrom…
Browse files Browse the repository at this point in the history
…Task (#3704)

<!-- Please be sure to read the
[Contribute](https://github.com/reactiveui/reactiveui#contribute)
section of the README -->

**What kind of change does this PR introduce?**
<!-- Bug fix, feature, docs update, ... -->

Fix for #1245
Fix for #2153
Fix for #3450

**What is the current behavior?**
<!-- You can also link to an open issue here. -->

ReactiveCommand does not properly support Cancellation tokens properly
for CreateFromTask due to an underlying issue in System.Reactive

**What is the new behavior?**
<!-- If this is a feature change -->

Fix the issues with the base functions within ReactiveCommand due to an
issue with Observable.FromAsync from System.Reactive by using a new
ObservableMixins.FromAsyncWithAllNotifications as the new function, this
extends Observable.FromAsync handling the error bubbling as required.

ObservableMixins.FromAsyncWithAllNotifications can be used to transform
a Cancellation Task into an Observable producing the expected
cancellation, errors and results.

**What might this PR break?**

ReactiveCommand.CreateFromTask will now handle exceptions as expected,
any existing workarounds could be removed once tested with actual
implementation in end users code.

**Please check if the PR fulfills these requirements**
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)

**Other information**:

Co-authored-by: @idg10 - created the base code in #3556
  • Loading branch information
ChrisPulman committed Jan 1, 2024
1 parent 2d7801e commit fb800f0
Show file tree
Hide file tree
Showing 9 changed files with 603 additions and 103 deletions.
Expand Up @@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFrameworks>net472;net6.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);MSB3243</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
Expand Down
Expand Up @@ -695,6 +695,9 @@ namespace ReactiveUI
}
public class ReactiveCommand<TParam, TResult> : ReactiveUI.ReactiveCommandBase<TParam, TResult>
{
protected ReactiveCommand([System.Runtime.CompilerServices.TupleElementNames(new string?[]?[] {
"Result",
"Cancel"})] System.Func<TParam, System.IObservable<System.ValueTuple<System.IObservable<TResult>, System.Action>>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
protected ReactiveCommand(System.Func<TParam, System.IObservable<TResult>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
public override System.IObservable<bool> CanExecute { get; }
public override System.IObservable<bool> IsExecuting { get; }
Expand Down
Expand Up @@ -695,6 +695,9 @@ namespace ReactiveUI
}
public class ReactiveCommand<TParam, TResult> : ReactiveUI.ReactiveCommandBase<TParam, TResult>
{
protected ReactiveCommand([System.Runtime.CompilerServices.TupleElementNames(new string?[]?[] {
"Result",
"Cancel"})] System.Func<TParam, System.IObservable<System.ValueTuple<System.IObservable<TResult>, System.Action>>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
protected ReactiveCommand(System.Func<TParam, System.IObservable<TResult>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
public override System.IObservable<bool> CanExecute { get; }
public override System.IObservable<bool> IsExecuting { get; }
Expand Down
Expand Up @@ -695,6 +695,9 @@ namespace ReactiveUI
}
public class ReactiveCommand<TParam, TResult> : ReactiveUI.ReactiveCommandBase<TParam, TResult>
{
protected ReactiveCommand([System.Runtime.CompilerServices.TupleElementNames(new string?[]?[] {
"Result",
"Cancel"})] System.Func<TParam, System.IObservable<System.ValueTuple<System.IObservable<TResult>, System.Action>>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
protected ReactiveCommand(System.Func<TParam, System.IObservable<TResult>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
public override System.IObservable<bool> CanExecute { get; }
public override System.IObservable<bool> IsExecuting { get; }
Expand Down
Expand Up @@ -693,6 +693,9 @@ namespace ReactiveUI
}
public class ReactiveCommand<TParam, TResult> : ReactiveUI.ReactiveCommandBase<TParam, TResult>
{
protected ReactiveCommand([System.Runtime.CompilerServices.TupleElementNames(new string?[]?[] {
"Result",
"Cancel"})] System.Func<TParam, System.IObservable<System.ValueTuple<System.IObservable<TResult>, System.Action>>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
protected ReactiveCommand(System.Func<TParam, System.IObservable<TResult>> execute, System.IObservable<bool>? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { }
public override System.IObservable<bool> CanExecute { get; }
public override System.IObservable<bool> IsExecuting { get; }
Expand Down

0 comments on commit fb800f0

Please sign in to comment.