How do I unsubscribe all handlers from an event for a particular class in C#?

后端 未结 5 1605
滥情空心
滥情空心 2020-12-08 07:04

Basic premise:

I have a Room which publishes an event when an Avatar \"enters\" to all Avatars within the Room. When an Avatar leaves the Room I want it to remove a

5条回答
  •  误落风尘
    2020-12-08 07:36

    What I'd like to do is in debug (do not think that this is good performance wise for release and one should catch it during development) throw exceptions when a class's events are not unsubscribed, this is the method that I use:

    #if DEBUG
    private void CheckEventHasNoSubscribers(Delegate eventDelegate)
    {
        if (eventDelegate != null)
            if (eventDelegate.GetInvocationList().Length != 0)
            {
                var subscriberCount = eventDelegate.GetInvocationList().Length;
    
                // determine the consumers of this event
                var subscribers = new StringBuilder();
                foreach (var del in eventDelegate.GetInvocationList())
                    subscribers.AppendLine((subscribers.Length != 0 ? ", " : "") + del.Target);
    
                // throw an exception listing all current subscription that would hinder GC on them!
                throw new Exception(
                    $"Event:{eventDelegate.Method.Name} still has {subscriberCount} subscribers, with the following targets [{subscribers}]");
            }
    }
    
    #endif
    

    The in my Dispose of the item that owns the delegate, or any other location where you're workflow supposed to release the object I would call it like this.

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (_orderCacheLock != null)
                _orderCacheLock.Dispose();
    
            if(_SettingTradeTimeOut!=null)
                _SettingTradeTimeOut.Dispose();
    
            _orderCacheLock = null;
    #if DEBUG
            CheckEventHasNoSubscribers(OnIsProfitable);
            CheckEventHasNoSubscribers(OnPropertyChanged);
    #endif
            disposedValue = true;
        }
    }
    

    It's then super easy to find the subscribers to these "orphaned" events and fix the code

    ps: An Extension of this "practice pattern" looks like this.

    public static void CheckEventHasNoSubscribers(this Delegate eventDelegate)
    {
        if (eventDelegate != null)
            if (eventDelegate.GetInvocationList().Length != 0)
            {
                var subscriberCount = eventDelegate.GetInvocationList().Length;
            // determine the consumers of this event
            var subscribers = new StringBuilder();
            foreach (var del in eventDelegate.GetInvocationList())
                subscribers.AppendLine((subscribers.Length != 0 ? ", " : "") + del.Target);
    
            // point to the missing un-subscribed events
            throw new Exception( $"Event:{eventDelegate.Method.Name} still has {subscriberCount} subscribers, with the following targets [{subscribers}]");
        }
    

    }

提交回复
热议问题