willyrs
willyrs

Reputation: 23

ReactiveUI - WhenActivated and Output Properties

I'm using ReactiveUI and I'm trying to change all my ViewModels' rules with WhenActivated but I'm unable understand how to have it working well in conjunction with output properties.

The pattern is something like

this.WhenActivated(
registerDisposable =>
{
    registerDisposable(this.Bind(…));
    registerDisposable(this.WhenAny(…));
    registerDisposable(this.WhenAnyValue(…));
});

and the output properties looks like

protected readonly ObservableAsPropertyHelper<object> _Obj;
public object Obj => _Obj.Value
_Obj = this.WhenAnyValue(x => x.Something).ToProperty(this, x => x.Obj, out _Obj);

So the only way I see to unite these is:

class MyClass {

protected readonly ObservableAsPropertyHelper<object> _Obj;
public object Obj => _Obj.Value

public MyClass()
{
    _Obj = this.WhenAnyValue(x => x.Something).ToProperty(this, x => x.Obj, out _Obj);

    this.WhenActivated( registerDisposable =>
    {
        registerDisposable(_Obj);
    });
}

}

Will this work as expected or there is another better way to do it?

Upvotes: 1

Views: 622

Answers (1)

Colt Bauman
Colt Bauman

Reputation: 662

In this case, _Obj doesn't need to be disposed of because Something has the same scope as _Obj (they're both contained within MyClass). However, if you were to base _Obj off of an observable contained in a service - which commonly has a longer lifetime than a view model - then you'd need to dispose of it.

// _Obj should be disposed of, in this case.
_Obj = someService
    .SomePipeline
    .ToProperty(this, x => x.Obj)

Side note: you don't need to use the out parameter if you're assigning to a value. The following is equivalent to the above:

someService
    .SomePipeline
    .ToProperty(this, x => x.Obj, out _Obj)

So in the case of someService, you could put _Obj inside WhenActivated but it

creates sticky race conditions whereby the OAPH may be null when it's corresponding property (Obj) is accessed too early.

This info, as well as the quote above, is taken straight from Kent Boogaart's book, "You, I, and ReactiveUI."

He was kind enough to provide a solution for the above scenario that turns activation into a pipeline. You can use these extensions (the first for view models and the second for views) like this:

_Obj = this
    .GetIsActivated()
    .Select(isActivated => isActivated ? someService.SomePipeline : Observable.Return(null))
    .Switch()
    .ToProperty(this, x => x.Obj);

Upvotes: 2

Related Questions