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 ?
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 ?
assuming a pub/sub environment, just call provider.Unsubscribe(EventType,subscriber) and let the provider determine whether the subscriber is subscribed or not
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.
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)
{
}
}`
There are two ways you can do this:
.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.