Question

I have a use case where i have to unsubscribe for an event. But prior to unsubscribing i want to make sure whether this guy has actully hooked on to this event or not.

Please let me know how i can achieve this ?

Was it helpful?

Solution

The sample class Publisher provides one event Publish. The method IsRegistered queries the events attached event handlers for the given class instance and returns true if there is at least one registered / attached event handler by this class instance. The overriden IsRegistered method does the same but for static types.

Put this code into a console application project and hit F5 to debug, give it a try.

internal class Publisher
{
    internal event EventHandler<EventArgs> Publish;

    internal bool IsRegistered(Type type)
    {
        if (Publish == null) return false;
        //
        return (from item in Publish.GetInvocationList() where item.Target == null & item.Method.DeclaringType == type select item).Count() > 0;

    }
    internal bool IsRegistered(object instance)
    {
        if (Publish == null) return false;
        //
        return (from item in Publish.GetInvocationList() where item.Target == instance select item).Count() > 0;
    }

    static int Main(string[] args)
    {
        Publisher p = new Publisher();
        //
        p.Publish += new EventHandler<EventArgs>(static_Publish);
        p.Publish += new EventHandler<EventArgs>(p.instance_Publish);            
        //
        Console.WriteLine("eventhandler static_Publish attach: {0}", p.IsRegistered(typeof(Program)));
        Console.WriteLine("eventhandler instance_Publish attach: {0}", p.IsRegistered(program));
        //
        return 0;
    }

    void instance_Publish(object sender, EventArgs e)
    {

    }
    static void static_Publish(object sender, EventArgs e)
    {

    }
}`

OTHER TIPS

From Microsoft:

        // Wrap event invocations inside a protected virtual method
        // to allow derived classes to override the event invocation behavior
        protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of
            // a race condition if the last subscriber unsubscribes
            // immediately after the null check and before the event is raised.
            EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

            // Event will be null if there are no subscribers
            if (handler != null)
            {
                // Format the string to send inside the CustomEventArgs parameter
                e.Message += String.Format(" at {0}", DateTime.Now.ToString());

                // Use the () operator to raise the event.
                handler(this, e);
            }
        }

You're looking for the if (handler != null) part. It's null if there are not any subscribers, not null if there are subscribers.

assuming a pub/sub environment, just call provider.Unsubscribe(EventType,subscriber) and let the provider determine whether the subscriber is subscribed or not

There are two ways you can do this:

  1. You can create a new delegate chain, with the delegate that is unsubscribing removed, and compare to the one you got before you save it. In the case where you're unsubscribing a delegate that has subscribed, you will get back a new delegate chain, without that delegate. In the case where you're trying to unsubscribe a delegate that has not subscribed, you will get back the same chain as the one you had.
  2. You can manually walk the delegate chain to see if the delegate you want to unsubscribe is present. This can be done using the normal Linq methods like .Contains for simplicity.

The first case can look like the code below. This will create a new delegate chain in a temporary variable, with the delegate you want to removed, removed, and then compare the temp chain to the existing chain. If they're the same, the delegate was not present.

private EventHandler _Changed;
public event EventHandler Changed
{
    add
    {
        _Changed += value;
    }
    remove
    {
        EventHandler temp = _Changed - value;
        if (_Changed == null || temp == _Changed)
            throw new InvalidOperationException(
                "Delegate is not subscribed, cannot unsubscribe");
        _Changed = temp;
    }
}

The second like the code below, this will simply see if the delegate you want to unsubscribe is present in the chain of delegates.

private EventHandler _Changed;
public event EventHandler Changed
{
    add
    {
        _Changed += value;
    }

    remove
    {
        if (_Changed == null || !_Changed.GetInvocationList().Contains(value))
            throw new InvalidOperationException(
                "Delegate is not subscribed, cannot unsubscribe");
        _Changed -= value;
    }
}

Note that you could, if you want, use similar code to handle the case where a delegate is being added twice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top