使用ObservableAsPropertyHelper激活/停用

时间:2019-05-08 03:52:27

标签: c# dispose reactiveui

与ObservableAsPropertyHelper一起使用时,激活/停用的正确用法是什么?给定一个反映长期(热)可观察对象的视图和视图模型,则在卸载视图和视图模型时需要处置订阅。但是,建议将其视为只读的ObservableAsPropertyHelper是在视图模型的构造函数中分配的,并且不能成为激活/停用生命周期的一部分。处理这类情况的正确方法是什么?

public interface ILongLivedObject
{
    IObservable<bool> Status { get; }
}


public class TestViewModel : ReactiveObject
{
    private readonly ObservableAsPropertyHelper<bool> _status;
    public bool Status => _status.Value;

    public TestViewModel(ILongLivedObject obj)
    {
         _status = obj.Status.ToProperty(this, vm => vm.Status); //how is the subscription disposed?
    }


}

在尝试添加依赖于此状态的命令时,这也使我陷入困境。在我的应用程序中,一个常见的用例是拥有某些处于特定状态的硬件(例如IsOpen),并在其为true时允许命令。 在不了解的情况下,这就是我要尝试做的事情:


public class TestViewModel : ReactiveObject
{
    private readonly ObservableAsPropertyHelper<bool> _status;
    public bool Status => _status.Value;

    public ReactiveCommand<Unit, Unit> DoStuff {get;}

    public TestViewModel(ILongLivedObject obj)
    {
         _status = obj.Status.ToProperty(this, vm => vm.Status); //how is the subscription disposed?
         DoStuff = ReactiveCommand.CreateFromTask(....., this.WhenAnyValue(this, x => x.Status);
    }


}

如果我尝试将_status创建移至此状态。激活后,该应用将崩溃,因为命令试图在创建前获取状态值。我应该在激活期间创建(重新)命令吗?这似乎是错误的,而且成本很高?

到目前为止,似乎最好有一个带有受保护的setter的常规Status属性并在this.WhenActivated中进行常规订阅-但这是手册告诉我们避免使用“只读”属性的原因。

1 个答案:

答案 0 :(得分:1)

因此在Reactive编程中要注意的一件事,处理掉通常意味着“退订”。

您通常不需要取消订阅,因为垃圾收集器会为您处理它,前提是您仅使用从当前ViewModel生成的可观察对象创建ObservableAsPropertyHelper(缩写为OAPH)。

但是,在您的情况下,您的可观察对象/对象与当前ViewModel之外的对象相关。 OAPH本身是一次性对象。

因此,您可以使用ISupportsActivation(很快将替换为IActivableViewModel)并将OAPH传递到其Disposable属性中。

public class TestViewModel : ReactiveObject, ISupportsActivation
{
    private readonly ObservableAsPropertyHelper<bool> _status;
    public bool Status => _status.Value;
    public ViewModelActivator Activator { get; } = new ViewModelActivator();

    public TestViewModel(ILongLivedObject obj)
    {
         _status = obj.Status.ToProperty(this, vm => vm.Status);
         this.WhenActivated(disposables =>
         {
             disposables(_status);
         }
    }
}

传递给disposables lambda的WhenActivated参数是一个使用IDisposable

的Func

在视图中,请确保派生IActivatable(即将重命名为IActivatableView),并在视图的构造函数中也使用WhileActivated。