How to Determine If an Event Is Already Subscribed

How to determine if an event is already subscribed

The event keyword was explicitly invented to prevent you from doing what you want to do. It restricts access to the underlying delegate object so nobody can directly mess with the events handler subscriptions that it stores. Events are accessors for a delegate, just like a property is an accessor for a field. A property only permits get and set, an event only permits add and remove.

This keeps your code safe, other code can only remove an event handler if it knows the event handler method and the target object. The C# language puts an extra layer of security in place by not allowing you to name the target object.

And WinForms puts an extra layer of security in place so it becomes difficult even if you use Reflection. It stores delegate instances in an EventHandlerList with a secret "cookie" as the key, you'd have to know the cookie to dig the object out of the list.

Well, don't go there. It is trivial to solve your problem with a bit of code on your end:

private bool mSubscribed;

private void Subscribe(bool enabled)
{
if (!enabled) textBox1.VisibleChanged -= textBox1_VisibleChanged;
else if (!mSubscribed) textBox1.VisibleChanged += textBox1_VisibleChanged;

mSubscribed = enabled;
}

How can I check if an event has been subscribed to, in .NET?

you cannot do this from subscriber to the event. Only publisher can check if there are any subscribers. You will need to keep track of subscription using some other mechanism in your class like:

UploadFolderMessageQueue.ReceiveCompleted += UploadMSMQReceiveCompleted;
bool handlerAttached=true;

then you can use this:

if(handlerAttached)
{
//DO YOUR STUFF
}

How to find all methods currently subscribed to an event in WPF / C# during debugging in Visual Studio

In most cases, Find All References should have it covered, but this fails when the event is not unique enough (imagine Button.Click).

You can access this in a debugger by browsing to the event object and examining the _invocationList field. If this field is not populated, look at _methodPtr field. If both fields are null, then no one is subscribed.

_target is the object containing the subscribed method. If it is null, a static method is subscribed (which makes identification much more tricky). Otherwise, you can dump the method table of the target object to find the subscribed method.

In Visual studio, the debug tooltips make this easy. For a unicast delegate, hovering over the event shows the declaring type and method name (and arity if needed):

screencap showing debugger tooltip

for multicast, the _invocationList takes over:

screencap showing debugger tooltip

Checking if event subscription has been performed

Simplest way is to use a flag to track the state of the subscription.

private bool isSubed;

private void Awake()
{
buttonManager.RepeatBetPressed += FinishWaiting;
isSubed = true;
}

private void OnDestroy()
{
buttonManager.RepeatBetPressed -= FinishWaiting;
}

private void OnEnable()
{
if(isSubed) { return; }
buttonManager.RepeatBetPressed += FinishWaiting;
}

private void OnDisable()
{
buttonManager.RepeatBetPressed -= FinishWaiting; // Minus here to remove
isSubed = false;
}

private void FinishWaiting()
{
// If for any reason, your object is still subed but does not exist
if(this == null){ return; }
}

How to find out whether somebody has subscribed to an event?

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)
{

}
}`

How do I get the subscribers of an event?

C# events/delegates are multicast, so the delegate is itself a list. From within the class, to get individual callers, you can use:

if (field != null) 
{
// or the event-name for field-like events
// or your own event-type in place of EventHandler
foreach(EventHandler subscriber in field.GetInvocationList())
{
// etc
}
}

However, to assign all at once, just use += or direct assignment:

SomeType other = ...
other.SomeEvent += localEvent;

Check if a specific event handler method already attached

No. You cannot.

The event keyword was explicitly invented to prevent you from doing what you want to do. It makes the delegate object for the event inaccessible so nobody can mess with the events handlers.

Source : How to dermine if an event is already subscribed

Fire an event when an event is subscribed to

Found the solution based on this thread.

public event EventHandler Inactivity
{
add
{
Inactivity += value;
if (!IsAlreadyCheckingForActivity)
{
StartActivityCheck();
}

}
remove
{
Inactivity -= value;
}
}

"Be careful if your function should be thread-safe, in which case you need a lock in order to ensure it to be synched."



Related Topics



Leave a reply



Submit