This is a bit of a difficult one to explain, first look at the code:
public static IObservable<bool> NotNullAnd<T>(IReadOnlyReactiveProperty<T> prop,
Func<T, IObservable<bool>> andSelector)
{
var notNull = prop.Select(l => l != null);
var isExecuting = prop
.Where(l => l != null)
.SelectMany(l => andSelector(l));
return notNull.CombineLatest(isExecuting, (x, y) => x && y);
}
This code seems to work but im not sure if this is the best way to do this.
Basically im looking for a way to check when an observable on an object triggers but that object could be null so I need to first check that. So the combination is check for when the property changes, if not null then listen for another property on the object... Difficult to explain but perhaps the tests might help explain:
private class Loader
{
public ReactiveProperty<bool> IsExecuting
= new ReactiveProperty<bool>();
}
[Test]
public void TestNotNullAnd()
{
var loaderProp = new ReactiveProperty<Loader>();
var isExecutingProp = NotNullAnd(loaderProp, l => l.IsExecuting)
.ToReadOnlyReactiveProperty();
var loader = new Loader();
Assert.IsFalse(isExecutingProp.Value);
loaderProp.Value = loader;
Assert.IsFalse(isExecutingProp.Value);
loaderProp.Value.IsExecuting.Value = true;
Assert.IsTrue(isExecutingProp.Value);
loaderProp.Value.IsExecuting.Value = false;
Assert.IsFalse(isExecutingProp.Value);
loaderProp.Value.IsExecuting.Value = true;
Assert.IsTrue(isExecutingProp.Value);
loaderProp.Value.IsExecuting.Value = false;
Assert.IsFalse(isExecutingProp.Value);
loaderProp.Value.IsExecuting.Value = true;
Assert.IsTrue(isExecutingProp.Value);
loaderProp.Value = null;
Assert.IsFalse(isExecutingProp.Value);
loaderProp.Value = loader;
Assert.IsTrue(isExecutingProp.Value);
}
As mentioned, all these tests pass but im not sure if there is a better way of doing it, plus im concerned that im introducing a memory leak in here somewhere because im not disposing of the listen to "l.IsExecuting"
Im using the "UniRx" libary for Unity.
Corrected answer: Ah, I see now that you want nulls from
prop
to emitfalse
s. In this case, you can simply map your nulls to wrappedfalse
that get flattened into the return stream:Obselete answer:
The nulls are already filtered out ofprop
's values withWhere(l => l != null)
, so constructingnotNull
and combining it intoisExecuting
is redundant. Furthermore, it is dangerous becausenotNull
andisExecuting
might not be perfectly in sync and you could flip some values unexpectedly, especially as you chain more operators.The following should be enough: