diff --git a/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj b/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj
index 97f8921f0d..02b11016d6 100644
--- a/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj
+++ b/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj
@@ -7,12 +7,12 @@
-
-
+
+
-
+
diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt
index f638f385fd..54ae8b01fe 100644
--- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt
+++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt
@@ -458,13 +458,8 @@ namespace ReactiveUI
public string PropertyName { get; set; }
}
public delegate void PropertyChangingEventHandler(object sender, ReactiveUI.PropertyChangingEventArgs e);
- public abstract class ReactiveCommand : ReactiveUI.IHandleObservableErrors, System.IDisposable, System.Windows.Input.ICommand
+ public class static ReactiveCommand
{
- protected ReactiveCommand() { }
- public abstract System.IObservable CanExecute { get; }
- public abstract System.IObservable IsExecuting { get; }
- public abstract System.IObservable ThrownExceptions { get; }
- public event System.EventHandler System.Windows.Input.ICommand.CanExecuteChanged;
public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { }
public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { }
public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { }
@@ -480,11 +475,6 @@ namespace ReactiveUI
public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { }
public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { }
public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { }
- public void Dispose() { }
- protected abstract void Dispose(bool disposing);
- protected abstract bool ICommandCanExecute(object parameter);
- protected abstract void ICommandExecute(object parameter);
- protected void OnCanExecuteChanged() { }
}
public class ReactiveCommand : ReactiveUI.ReactiveCommandBase
{
@@ -496,12 +486,19 @@ namespace ReactiveUI
public override System.IObservable Execute(TParam parameter = null) { }
public override System.IDisposable Subscribe(System.IObserver observer) { }
}
- public abstract class ReactiveCommandBase : ReactiveUI.ReactiveCommand, System.IObservable
+ public abstract class ReactiveCommandBase : ReactiveUI.IHandleObservableErrors, System.IDisposable, System.IObservable, System.Windows.Input.ICommand
{
protected ReactiveCommandBase() { }
+ public abstract System.IObservable CanExecute { get; }
+ public abstract System.IObservable IsExecuting { get; }
+ public abstract System.IObservable ThrownExceptions { get; }
+ public event System.EventHandler System.Windows.Input.ICommand.CanExecuteChanged;
+ public void Dispose() { }
+ protected abstract void Dispose(bool disposing);
public abstract System.IObservable Execute(TParam parameter = null);
- protected override bool ICommandCanExecute(object parameter) { }
- protected override void ICommandExecute(object parameter) { }
+ protected virtual bool ICommandCanExecute(object parameter) { }
+ protected virtual void ICommandExecute(object parameter) { }
+ protected void OnCanExecuteChanged() { }
public abstract System.IDisposable Subscribe(System.IObserver observer);
}
public class static ReactiveCommandMixins
diff --git a/src/ReactiveUI.Tests/CommandBindingTests.cs b/src/ReactiveUI.Tests/CommandBindingTests.cs
index db6ae4e153..5e0ad81564 100755
--- a/src/ReactiveUI.Tests/CommandBindingTests.cs
+++ b/src/ReactiveUI.Tests/CommandBindingTests.cs
@@ -17,7 +17,7 @@ namespace ReactiveUI.Tests
{
public class FakeViewModel : ReactiveObject
{
- public ReactiveCommand Cmd { get; protected set; }
+ public ReactiveCommand Cmd { get; protected set; }
public FakeViewModel()
{
@@ -123,9 +123,9 @@ public void EventBinderBindsToImplicitEvent()
public class CommandBindViewModel : ReactiveObject
{
- public ReactiveCommand _Command1;
+ public ReactiveCommand _Command1;
- public ReactiveCommand Command1
+ public ReactiveCommand Command1
{
get => _Command1;
set => this.RaiseAndSetIfChanged(ref _Command1, value);
@@ -141,7 +141,7 @@ public ReactiveCommand Command2
public CommandBindViewModel()
{
- Command1 = ReactiveCommand.Create(() => { });
+ Command1 = ReactiveCommand.Create(_ => Unit.Default);
Command2 = ReactiveCommand.Create(() => { });
}
@@ -163,7 +163,7 @@ public FakeNestedViewModel()
NestedCommand = ReactiveCommand.Create(() => { });
}
- public ReactiveCommand NestedCommand { get; protected set; }
+ public ReactiveCommand NestedCommand { get; protected set; }
}
public class CustomClickButton : Button
@@ -235,7 +235,7 @@ public void CommandBindByNameWireup()
var disp = view.BindCommand(vm, x => x.Command1, x => x.Command1);
Assert.Equal(vm.Command1, view.Command1.Command);
- var newCmd = ReactiveCommand.Create(() => { });
+ var newCmd = ReactiveCommand.Create(_ => { });
vm.Command1 = newCmd;
Assert.Equal(newCmd, view.Command1.Command);
@@ -265,7 +265,7 @@ public void CommandBindSetsInitialEnabledState_True()
var view = new CommandBindView { ViewModel = vm };
var canExecute1 = new BehaviorSubject(true);
- var cmd1 = ReactiveCommand.Create(() => { }, canExecute1);
+ var cmd1 = ReactiveCommand.Create(_ => { }, canExecute1);
vm.Command1 = cmd1;
var disp = view.BindCommand(vm, x => x.Command1, x => x.Command1);
@@ -280,7 +280,7 @@ public void CommandBindSetsDisablesCommandWhenCanExecuteChanged()
var view = new CommandBindView { ViewModel = vm };
var canExecute1 = new BehaviorSubject(true);
- var cmd1 = ReactiveCommand.Create(() => { }, canExecute1);
+ var cmd1 = ReactiveCommand.Create(_ => { }, canExecute1);
vm.Command1 = cmd1;
var disp = view.BindCommand(vm, x => x.Command1, x => x.Command1);
@@ -299,7 +299,7 @@ public void CommandBindSetsInitialEnabledState_False()
var view = new CommandBindView { ViewModel = vm };
var canExecute1 = new BehaviorSubject(false);
- var cmd1 = ReactiveCommand.Create(() => { }, canExecute1);
+ var cmd1 = ReactiveCommand.Create(_ => { }, canExecute1);
vm.Command1 = cmd1;
var disp = view.BindCommand(vm, x => x.Command1, x => x.Command1);
@@ -314,7 +314,7 @@ public void CommandBindRaisesCanExecuteChangedOnBind()
var view = new CommandBindView { ViewModel = vm };
var canExecute1 = new BehaviorSubject(true);
- var cmd1 = ReactiveCommand.Create(() => { }, canExecute1);
+ var cmd1 = ReactiveCommand.Create(_ => { }, canExecute1);
vm.Command1 = cmd1;
var disp = view.BindCommand(vm, x => x.Command1, x => x.Command1);
@@ -323,7 +323,7 @@ public void CommandBindRaisesCanExecuteChangedOnBind()
// Now change to a disabled cmd
var canExecute2 = new BehaviorSubject(false);
- var cmd2 = ReactiveCommand.Create(() => { }, canExecute2);
+ var cmd2 = ReactiveCommand.Create(_ => { }, canExecute2);
vm.Command1 = cmd2;
Assert.False(view.Command1.IsEnabled);
diff --git a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs
index 6cd0e1c677..aed8643d3c 100755
--- a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs
+++ b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs
@@ -215,7 +215,7 @@ public void CommandBindToExplicitEventWireup()
public class FakeViewModel : ReactiveObject
{
- public ReactiveCommand Cmd { get; protected set; }
+ public ReactiveCommand Cmd { get; protected set; }
public FakeViewModel()
{
diff --git a/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj b/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj
index 6fa4fbf116..164684504d 100644
--- a/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj
+++ b/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj
@@ -8,17 +8,17 @@
-
+
-
-
-
-
-
+
+
+
+
+
-
+
diff --git a/src/ReactiveUI.Tests/WeakEventManagerTest.cs b/src/ReactiveUI.Tests/WeakEventManagerTest.cs
index a0b8fed1bc..e001f0b9bd 100755
--- a/src/ReactiveUI.Tests/WeakEventManagerTest.cs
+++ b/src/ReactiveUI.Tests/WeakEventManagerTest.cs
@@ -16,7 +16,7 @@ public class WeakEventManagerTest
public void ButtonDoesNotLeakTest()
{
var button = new Button();
- ReactiveCommand command = ReactiveCommand.Create(() => { });
+ var command = ReactiveCommand.Create(() => { });
button.Command = command;
var buttonRef = new WeakReference(button);
diff --git a/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs b/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs
index 9a54447763..dbbfb84691 100644
--- a/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs
+++ b/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs
@@ -56,14 +56,13 @@ public IReactiveBinding BindCommand Observable.Return(withParameter())), toEvent, cmd =>
{
- var rc = cmd as ReactiveCommand;
+ var rc = cmd as IReactiveCommand;
if (rc == null)
{
return new RelayCommand(cmd.CanExecute, _ => cmd.Execute(withParameter()));
}
- var ret = ReactiveCommand.Create(() => ((ICommand)rc).Execute(null), rc.CanExecute);
- return ret;
+ return ReactiveCommand.Create(() => ((ICommand)rc).Execute(null), rc.CanExecute);
});
return new ReactiveBinding(
diff --git a/src/ReactiveUI/EventManagers/WeakEventManager.cs b/src/ReactiveUI/EventManagers/WeakEventManager.cs
index 5f8fa574b3..71674cdba6 100644
--- a/src/ReactiveUI/EventManagers/WeakEventManager.cs
+++ b/src/ReactiveUI/EventManagers/WeakEventManager.cs
@@ -293,11 +293,11 @@ public bool Matches(object source, TEventHandler handler)
ReferenceEquals(_source.Target, source) &&
_originalHandler != null &&
(ReferenceEquals(_originalHandler.Target, handler) ||
- _originalHandler.Target is PropertyChangedEventHandler eventHandler &&
+ (_originalHandler.Target is PropertyChangedEventHandler eventHandler &&
handler is PropertyChangedEventHandler &&
Equals(
eventHandler.Target,
- (handler as PropertyChangedEventHandler)?.Target));
+ (handler as PropertyChangedEventHandler)?.Target)));
}
}
diff --git a/src/ReactiveUI/Platforms/uap10.0.16299/WinRTAutoSuspendApplication.cs b/src/ReactiveUI/Platforms/uap10.0.16299/WinRTAutoSuspendApplication.cs
index 8e48691ea1..1f63c794c7 100644
--- a/src/ReactiveUI/Platforms/uap10.0.16299/WinRTAutoSuspendApplication.cs
+++ b/src/ReactiveUI/Platforms/uap10.0.16299/WinRTAutoSuspendApplication.cs
@@ -20,8 +20,8 @@ namespace ReactiveUI
///
/// AutoSuspend-based Application. To use AutoSuspend with WinRT, change your
/// Application to inherit from this class, then call:
- ///
- /// Locator.Current.GetService.().SetupDefaultSuspendResume();
+ /// Locator.Current.GetService.<ISuspensionHost>().SetupDefaultSuspendResume();
+ /// This will register your suspension host.
///
public class AutoSuspendHelper : IEnableLogger
{
diff --git a/src/ReactiveUI/ReactiveCommand/IReactiveCommand.cs b/src/ReactiveUI/ReactiveCommand/IReactiveCommand.cs
new file mode 100644
index 0000000000..b211c4978e
--- /dev/null
+++ b/src/ReactiveUI/ReactiveCommand/IReactiveCommand.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace ReactiveUI
+{
+ ///
+ /// Encapsulates a user action behind a reactive interface.
+ /// This is for interop inside for the command binding.
+ /// Not meant for external use due to the fact it doesn't implement ICommand
+ /// to force the user to favor the Reactive style command execution.
+ ///
+ internal interface IReactiveCommand : IDisposable, IHandleObservableErrors
+ {
+ ///
+ /// Gets an observable whose value indicates whether the command is currently executing.
+ ///
+ ///
+ /// This observable can be particularly useful for updating UI, such as showing an activity indicator whilst a command
+ /// is executing.
+ ///
+ IObservable IsExecuting { get; }
+
+ ///
+ /// Gets an observable whose value indicates whether the command can currently execute.
+ ///
+ ///
+ /// The value provided by this observable is governed both by any canExecute observable provided during
+ /// command creation, as well as the current execution status of the command. A command that is currently executing
+ /// will always yield false from this observable, even if the canExecute pipeline is currently true.
+ ///
+ IObservable CanExecute { get; }
+ }
+}
diff --git a/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs b/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs
index b1b764d42c..23ba5e5779 100644
--- a/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs
+++ b/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Linq.Expressions;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
@@ -14,7 +13,6 @@
using System.Reactive.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
-using System.Windows.Input;
namespace ReactiveUI
{
@@ -23,51 +21,10 @@ namespace ReactiveUI
///
///
///
- /// This non-generic base class defines the base behavior for all reactive commands.
- ///
- ///
- /// Reactive commands encapsulate the behavior of running some execution logic and then surfacing the results on the UI
- /// thread. Importantly, no scheduling is performed against input observables (the canExecute and execution pipelines).
- ///
- ///
- /// To create an instance of ReactiveCommand, call one of the static creation methods defined by this class.
- /// can be used when your execution logic is synchronous.
- /// and
- /// (and overloads) can be used for asynchronous
- /// execution logic. Optionally, you can provide an observable that governs the availability of the command for execution,
- /// as well as a scheduler to which events will be delivered.
- ///
- ///
- /// The property provides an observable that can be used to determine whether the command is
- /// eligible for execution. The value of this observable is determined by both the canExecute observable provided
- /// during command creation, and the current execution status of the command. A command that is already executing will
- /// yield false from its observable regardless of the canExecute observable provided
- /// during command creation.
- ///
- ///
- /// The property provides an observable whose value indicates whether the command is currently
- /// executing. This can be a useful means of triggering UI, such as displaying an activity indicator whilst a command is
- /// executing.
- ///
- ///
- /// As discussed above, you are under no obligation to somehow incorporate this into your canExecute observable
- /// because that is taken care of for you. That is, if the value of IsExecuting is true, the value of
- /// CanExecute will be false. However, if the value of CanExecute is false, that does not imply
- /// the value of IsExecuting is true.
- ///
- ///
- /// Any errors in your command's execution logic (including any canExecute observable you choose to provide) will be
- /// surfaced via the observable. This gives you the opportunity to handle the error before
- /// it triggers a default handler that tears down the application. For example, you might use this as a means of alerting
- /// the user that something has gone wrong executing the command.
- ///
- ///
- /// For the sake of convenience, all ReactiveCommand instances are also implementations of .
- /// This allows you to easily integrate instances of ReactiveCommand into platforms that understands ICommand
- /// natively (such as WPF and UWP).
+ /// This non-generic base class defines the creation behavior of the ReactiveCommand's.
///
///
- public abstract partial class ReactiveCommand
+ public static class ReactiveCommand
{
///
/// Creates a parameterless with synchronous execution logic.
@@ -562,107 +519,6 @@ public static CombinedReactiveCommand CreateCombined
- /// Abstract base class of the ReactiveCommand's. Meant only for interop with the ICommand interface.
- ///
- public abstract partial class ReactiveCommand : IDisposable, ICommand, IHandleObservableErrors
- {
- private EventHandler _canExecuteChanged;
-
- ///
- event EventHandler ICommand.CanExecuteChanged
- {
- add => _canExecuteChanged += value;
- remove => _canExecuteChanged -= value;
- }
-
- ///
- /// An observable whose value indicates whether the command can currently execute.
- ///
- ///
- /// The value provided by this observable is governed both by any canExecute observable provided during
- /// command creation, as well as the current execution status of the command. A command that is currently executing
- /// will always yield false from this observable, even if the canExecute pipeline is currently true.
- ///
- public abstract IObservable CanExecute
- {
- get;
- }
-
- ///
- /// An observable whose value indicates whether the command is currently executing.
- ///
- ///
- /// This observable can be particularly useful for updating UI, such as showing an activity indicator whilst a command
- /// is executing.
- ///
- public abstract IObservable IsExecuting
- {
- get;
- }
-
- ///
- /// An observable that ticks any exceptions in command execution logic.
- ///
- ///
- /// Any exceptions that are not observed via this observable will propagate out and cause the application to be torn
- /// down. Therefore, you will always want to subscribe to this observable if you expect errors could occur (e.g. if
- /// your command execution includes network activity).
- ///
- public abstract IObservable ThrownExceptions
- {
- get;
- }
-
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- ///
- bool ICommand.CanExecute(object parameter)
- {
- return ICommandCanExecute(parameter);
- }
-
- ///
- void ICommand.Execute(object parameter)
- {
- ICommandExecute(parameter);
- }
-
- ///
- /// Disposes of the managed resources.
- ///
- /// If its getting called by the Dispose() method.
- protected abstract void Dispose(bool disposing);
-
- ///
- /// Will be called by the methods from the ICommand interface.
- /// This method is called when the Command should evaluate if it can execute.
- ///
- /// The parameter being passed to the ICommand.
- /// If the command can be executed.
- protected abstract bool ICommandCanExecute(object parameter);
-
- ///
- /// Will be called by the methods from the ICommand interface.
- /// This method is called when the Command should execute.
- ///
- /// The parameter being passed to the ICommand.
- protected abstract void ICommandExecute(object parameter);
-
- ///
- /// Will trigger a event when the CanExecute condition has changed.
- ///
- protected void OnCanExecuteChanged()
- {
- _canExecuteChanged?.Invoke(this, EventArgs.Empty);
- }
- }
-
///
/// Encapsulates a user interaction behind a reactive interface.
///
diff --git a/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs b/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs
index 4c2dd0fd8c..9276bca8e9 100644
--- a/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs
+++ b/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs
@@ -4,6 +4,7 @@
using System;
using System.Reactive.Linq;
+using System.Windows.Input;
namespace ReactiveUI
{
@@ -19,6 +20,47 @@ namespace ReactiveUI
/// Because the result type is known by this class, it can implement . However, the implementation
/// is defined as abstract, so subclasses must provide it.
///
+ ///
+ /// Reactive commands encapsulate the behavior of running some execution logic and then surfacing the results on the UI
+ /// thread. Importantly, no scheduling is performed against input observables (the canExecute and execution pipelines).
+ ///
+ ///
+ /// To create an instance of ReactiveCommand, call one of the static creation methods defined by this class.
+ /// can be used when your execution logic is synchronous.
+ /// and
+ /// (and overloads) can be used for asynchronous
+ /// execution logic. Optionally, you can provide an observable that governs the availability of the command for execution,
+ /// as well as a scheduler to which events will be delivered.
+ ///
+ ///
+ /// The property provides an observable that can be used to determine whether the command is
+ /// eligible for execution. The value of this observable is determined by both the canExecute observable provided
+ /// during command creation, and the current execution status of the command. A command that is already executing will
+ /// yield false from its observable regardless of the canExecute observable provided
+ /// during command creation.
+ ///
+ ///
+ /// The property provides an observable whose value indicates whether the command is currently
+ /// executing. This can be a useful means of triggering UI, such as displaying an activity indicator whilst a command is
+ /// executing.
+ ///
+ ///
+ /// As discussed above, you are under no obligation to somehow incorporate this into your canExecute observable
+ /// because that is taken care of for you. That is, if the value of IsExecuting is true, the value of
+ /// CanExecute will be false. However, if the value of CanExecute is false, that does not imply
+ /// the value of IsExecuting is true.
+ ///
+ ///
+ /// Any errors in your command's execution logic (including any canExecute observable you choose to provide) will be
+ /// surfaced via the observable. This gives you the opportunity to handle the error before
+ /// it triggers a default handler that tears down the application. For example, you might use this as a means of alerting
+ /// the user that something has gone wrong executing the command.
+ ///
+ ///
+ /// For the sake of convenience, all ReactiveCommand instances are also implementations of .
+ /// This allows you to easily integrate instances of ReactiveCommand into platforms that understands ICommand
+ /// natively (such as WPF and UWP).
+ ///
///
///
/// The type of parameter values passed in during command execution.
@@ -26,8 +68,74 @@ namespace ReactiveUI
///
/// The type of the values that are the result of command execution.
///
- public abstract class ReactiveCommandBase : ReactiveCommand, IObservable
+ public abstract class ReactiveCommandBase : IObservable, ICommand, IReactiveCommand
{
+ private EventHandler _canExecuteChanged;
+
+ ///
+ event EventHandler ICommand.CanExecuteChanged
+ {
+ add => _canExecuteChanged += value;
+ remove => _canExecuteChanged -= value;
+ }
+
+ ///
+ /// An observable whose value indicates whether the command can currently execute.
+ ///
+ ///
+ /// The value provided by this observable is governed both by any canExecute observable provided during
+ /// command creation, as well as the current execution status of the command. A command that is currently executing
+ /// will always yield false from this observable, even if the canExecute pipeline is currently true.
+ ///
+ public abstract IObservable CanExecute
+ {
+ get;
+ }
+
+ ///
+ /// An observable whose value indicates whether the command is currently executing.
+ ///
+ ///
+ /// This observable can be particularly useful for updating UI, such as showing an activity indicator whilst a command
+ /// is executing.
+ ///
+ public abstract IObservable IsExecuting
+ {
+ get;
+ }
+
+ ///
+ /// An observable that ticks any exceptions in command execution logic.
+ ///
+ ///
+ /// Any exceptions that are not observed via this observable will propagate out and cause the application to be torn
+ /// down. Therefore, you will always want to subscribe to this observable if you expect errors could occur (e.g. if
+ /// your command execution includes network activity).
+ ///
+ public abstract IObservable ThrownExceptions
+ {
+ get;
+ }
+
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ bool ICommand.CanExecute(object parameter)
+ {
+ return ICommandCanExecute(parameter);
+ }
+
+ ///
+ void ICommand.Execute(object parameter)
+ {
+ ICommandExecute(parameter);
+ }
+
///
/// Subscribes to execution results from this command.
///
@@ -69,14 +177,37 @@ public abstract class ReactiveCommandBase : ReactiveCommand, IO
///
public abstract IObservable Execute(TParam parameter = default(TParam));
- ///
- protected override bool ICommandCanExecute(object parameter)
+ ///
+ /// Disposes of the managed resources.
+ ///
+ /// If its getting called by the Dispose() method.
+ protected abstract void Dispose(bool disposing);
+
+ ///
+ /// Will trigger a event when the CanExecute condition has changed.
+ ///
+ protected void OnCanExecuteChanged()
+ {
+ _canExecuteChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ ///
+ /// Will be called by the methods from the ICommand interface.
+ /// This method is called when the Command should evaluate if it can execute.
+ ///
+ /// The parameter being passed to the ICommand.
+ /// If the command can be executed.
+ protected virtual bool ICommandCanExecute(object parameter)
{
return CanExecute.FirstAsync().Wait();
}
- ///
- protected override void ICommandExecute(object parameter)
+ ///
+ /// Will be called by the methods from the ICommand interface.
+ /// This method is called when the Command should execute.
+ ///
+ /// The parameter being passed to the ICommand.
+ protected virtual void ICommandExecute(object parameter)
{
// ensure that null is coerced to default(TParam) so that commands taking value types will use a sensible default if no parameter is supplied
if (parameter == null)
diff --git a/version.json b/version.json
index d9ea9db23f..8ca742c336 100644
--- a/version.json
+++ b/version.json
@@ -1,5 +1,5 @@
{
- "version": "9.1",
+ "version": "9.2",
"publicReleaseRefSpec": [
"^refs/heads/master$", // we release out of master
"^refs/heads/develop$", // we release out of develop