static IEnumerator PublishPocoValueChanged <TSource, TProperty>(WeakReference sourceReference, Func <TSource, TProperty> propertySelector, FrameCountType frameCountType, IObserver <TProperty> observer, CancellationToken cancellationToken) { var comparer = UnityEqualityComparer.GetDefault <TProperty>(); var isFirst = true; var currentValue = default(TProperty); var prevValue = default(TProperty); var yieldInstruction = frameCountType.GetYieldInstruction(); while (!cancellationToken.IsCancellationRequested) { var target = sourceReference.Target; if (target != null) { try { currentValue = propertySelector((TSource)target); } catch (Exception ex) { observer.OnError(ex); yield break; } finally { target = null; // remove reference(must need!) } } else { observer.OnCompleted(); yield break; } if (isFirst || !comparer.Equals(currentValue, prevValue)) { isFirst = false; observer.OnNext(currentValue); prevValue = currentValue; } yield return(yieldInstruction); } }
static IEnumerator PublishUnityObjectValueChanged <TSource, TProperty>(UnityEngine.Object unityObject, Func <TSource, TProperty> propertySelector, FrameCountType frameCountType, IObserver <TProperty> observer, CancellationToken cancellationToken) { var comparer = UnityEqualityComparer.GetDefault <TProperty>(); var isFirst = true; var currentValue = default(TProperty); var prevValue = default(TProperty); var yieldInstruction = frameCountType.GetYieldInstruction(); var source = (TSource)(object)unityObject; while (!cancellationToken.IsCancellationRequested) { if (unityObject != null) { try { currentValue = propertySelector(source); } catch (Exception ex) { observer.OnError(ex); yield break; } } else { observer.OnCompleted(); yield break; } if (isFirst || !comparer.Equals(currentValue, prevValue)) { isFirst = false; observer.OnNext(currentValue); prevValue = currentValue; } yield return(yieldInstruction); } }
/// <summary> /// Publish target property when value is changed. If source is destroyed/destructed, publish OnCompleted. /// </summary> /// <param name="fastDestroyCheck">If true and target is UnityObject, use destroyed check by additional component. It is faster check for lifecycle but needs initial cost.</param> public static IObservable <TProperty> ObserveEveryValueChanged <TSource, TProperty>(this TSource source, Func <TSource, TProperty> propertySelector, FrameCountType frameCountType, IEqualityComparer <TProperty> comparer, bool fastDestroyCheck) where TSource : class { if (source == null) { return(Observable.Empty <TProperty>()); } if (comparer == null) { comparer = UnityEqualityComparer.GetDefault <TProperty>(); } var unityObject = source as UnityEngine.Object; var isUnityObject = source is UnityEngine.Object; if (isUnityObject && unityObject == null) { return(Observable.Empty <TProperty>()); } // MicroCoroutine does not publish value immediately, so publish value on subscribe. if (isUnityObject) { return(ObservableUnity.FromMicroCoroutine <TProperty>((observer, cancellationToken) => { if (unityObject != null) { var firstValue = default(TProperty); try { firstValue = propertySelector((TSource)(object)unityObject); } catch (Exception ex) { observer.OnError(ex); return EmptyEnumerator(); } observer.OnNext(firstValue); return PublishUnityObjectValueChanged(unityObject, firstValue, propertySelector, comparer, observer, cancellationToken, fastDestroyCheck); } else { observer.OnCompleted(); return EmptyEnumerator(); } }, frameCountType)); } else { var reference = new WeakReference(source); source = null; return(ObservableUnity.FromMicroCoroutine <TProperty>((observer, cancellationToken) => { var target = reference.Target; if (target != null) { var firstValue = default(TProperty); try { firstValue = propertySelector((TSource)target); } catch (Exception ex) { observer.OnError(ex); return EmptyEnumerator(); } finally { target = null; } observer.OnNext(firstValue); return PublishPocoValueChanged(reference, firstValue, propertySelector, comparer, observer, cancellationToken); } else { observer.OnCompleted(); return EmptyEnumerator(); } }, frameCountType)); } }
/// <summary> /// Publish target property when value is changed. If source is destroyed/destructed, publish OnCompleted. /// </summary> /// <param name="fastDestroyCheck">If true and target is UnityObject, use destroyed check by additional component. It is faster check for lifecycle but needs initial cost.</param> public static IObservable <TProperty> ObserveEveryValueChanged <TSource, TProperty>(this TSource source, Func <TSource, TProperty> propertySelector, FrameCountType frameCountType = FrameCountType.Update, bool fastDestroyCheck = false) where TSource : class { return(ObserveEveryValueChanged(source, propertySelector, frameCountType, UnityEqualityComparer.GetDefault <TProperty>(), fastDestroyCheck)); }
public static UniRx.IObservable <TProperty> ObserveEveryValueChanged <TSource, TProperty>(this TSource source, Func <TSource, TProperty> propertySelector, FrameCountType frameCountType, IEqualityComparer <TProperty> comparer, bool fastDestroyCheck) where TSource : class { if (source == null) { return(Observable.Empty <TProperty>()); } if (comparer == null) { comparer = UnityEqualityComparer.GetDefault <TProperty>(); } UnityEngine.Object unityObject = source as UnityEngine.Object; bool flag = source is UnityEngine.Object; if (flag && unityObject == null) { return(Observable.Empty <TProperty>()); } if (flag) { return(Observable.FromMicroCoroutine(delegate(UniRx.IObserver <TProperty> observer, CancellationToken cancellationToken) { if (unityObject != null) { TProperty val2 = default(TProperty); try { val2 = propertySelector((TSource)(object)unityObject); } catch (Exception error2) { observer.OnError(error2); return EmptyEnumerator(); } observer.OnNext(val2); return PublishUnityObjectValueChanged(unityObject, val2, propertySelector, comparer, observer, cancellationToken, fastDestroyCheck); } observer.OnCompleted(); return EmptyEnumerator(); }, frameCountType)); } WeakReference reference = new WeakReference(source); source = (TSource)null; return(Observable.FromMicroCoroutine(delegate(UniRx.IObserver <TProperty> observer, CancellationToken cancellationToken) { object target = reference.Target; if (target != null) { TProperty val = default(TProperty); try { val = propertySelector((TSource)target); } catch (Exception error) { observer.OnError(error); return EmptyEnumerator(); } finally { target = null; } observer.OnNext(val); return PublishPocoValueChanged(reference, val, propertySelector, comparer, observer, cancellationToken); } observer.OnCompleted(); return EmptyEnumerator(); }, frameCountType)); }