Reputation: 23
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
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