Creating a weak subscription to an IObservable

前端 未结 6 1339
暗喜
暗喜 2021-02-01 05:05

What I want to do is ensure that if the only reference to my observer is the observable, it get\'s garbage collected and stops receiving messages.

Say I have a control w

6条回答
  •  醉话见心
    2021-02-01 05:31

    The key is to recognize that you are going to have to pass in both the target and a two-parameter action. A one-parameter action will never do it, because either you use a weak reference to your action (and the action gets GC'd), or you use a strong reference to your action, which in turn has a strong reference to the target, so the target can't get GC'd. Keeping that in mind, the following works:

    using System;
    
    namespace Closures {
      public static class WeakReferenceExtensions {
        ///  returns null if target is not available. Safe to call, even if the reference is null. 
        public static TTarget TryGetTarget(this WeakReference reference) where TTarget : class {
          TTarget r = null;
          if (reference != null) {
            reference.TryGetTarget(out r);
          }
          return r;
        }
      }
      public static class ObservableExtensions {
    
        public static IDisposable WeakSubscribe(this IObservable source, T target, Action action)
          where T : class {
          var weakRef = new WeakReference(target);
          var r = source.Subscribe(u => {
            var t = weakRef.TryGetTarget();
            if (t != null) {
              action(t, u);
            }
          });
          return r;
        }
      }
    }
    

    Sample Observable:

    using System;
    using System.Reactive.Subjects;
    
    namespace Closures {
      public class Observable {
        public IObservable ObservableProperty => _subject;
        private Subject _subject = new Subject();
        private int n;
        public void Fire() {
          _subject.OnNext(n++);
        }
      }
    }
    

    Usage:

    Class SomeClass {
    
     IDisposable disposable;
    
     public void SomeMethod(Observable observeMe) {
       disposable = observeMe.ObservableProperty.WeakSubscribe(this, (wo, n) => wo.Log(n));
     }
    
      public void Log(int n) {
        System.Diagnostics.Debug.WriteLine("log "+n);
      }
    }
    

提交回复
热议问题