Weak events in .NET?

后端 未结 9 1977
没有蜡笔的小新
没有蜡笔的小新 2020-12-04 16:37

If object A listens to an event from object B, object B will keep object A alive. Is there a standard implementation of weak events that would prevent this? I know WPF has s

相关标签:
9条回答
  • 2020-12-04 17:32

    Dustin Campbell from the DidItWith.NET blog examines several of the failed attempts to create weak event handlers, then goes on to show a valid, working, lightweight implementation: Solving the Problem With Weak Event Handlers.

    Ideally, though, Microsoft would introduce the concept into the language itself. Something like:

    Foo.Clicked += new weak EventHandler(...);
    

    If you feel this feature is important to you, please vote for it here.

    0 讨论(0)
  • 2020-12-04 17:34

    Be careful when using weak events implementations. Weak events appear to remove from the subscriber the responsibility of unsubscribing from the event (or message). In that case event handlers may be invoked even after the subscriber "goes out of scope". Take a subscriber that does not explicitly unsubscribe and that becomes garbage collectable but is not yet garbage collected. The weak event manager will not be able to detect that state and because of that it will still call the event handler of that subscriber. This can lead to all kind of unexpected side effects.

    See more details at The Weak Event Pattern is Dangerous.
    See this source code that illustrates this issue using the MvvMCross messaging plugin as a weak event manager.

    0 讨论(0)
  • 2020-12-04 17:35

    What advantages does Dustin's implementation have compared to the WPF's WeakEventManager class which simply wraps the target object as well as the delegate into a weak reference:

    public Listener(object target, Delegate handler)
      {
           this._target = new WeakReference(target);
           this._handler = new WeakReference((object) handler);
      }
    

    In my opinion this approach is more flexible, since it does not require the implementation to pass the target instance as a parameter during the invocation of the event handler:

    public void Invoke(object sender, E e)
            {
                T target = (T)m_TargetRef.Target;
    
                if (target != null)
                    m_OpenHandler(target, sender, e);
    

    This also allows the use of anomymous methods instead of an instance method (that seems to be also a disadvantage of the Dustin's implementation).

    0 讨论(0)
提交回复
热议问题