Andrew
Andrew

Reputation: 2335

C# Accessing event names from a form control using reflection

I am currently working on an ongoing solution, which takes an assembly containing forms, creates instances of those forms and then extracts the controls from them. All good so far. However, I've been given another request, which I am finding harder to implement.

What I need to do now is extract, at runtime the events associated with each control on the form (specifically the actual event name and the event type). To facilitate this I've created a very simple winforms project to mimic what I will be doing in the completed application.

I've tried a variety of ways to get these events and the closest I have come so far, is with the following:

EventHandlerList events = this.button1.GetType()
                                      .GetProperty("Events", BindingFlags.Instance | 
                                                             BindingFlags.Public |
                                                             BindingFlags.Static | 
                                                             BindingFlags.NonPublic)
                                      .GetValue(this.button1) as EventHandlerList;

Within my button I have created 2 events for click and mouse leave. When I debug the code above and examine events I can see the two I have created, but they exist under "None-public members\head".

The event I can see in debug mode looks something like:

{Method = {Void button1_MouseLeave(System.Object, System.EventArgs)}}

Following advice on another form I tried the following to see if I could create a delegate of the event (and it didn't work):

var myEvent = events["button1_MouseLeave"];

I'm not sure where to go from here. I seem to be almost there, in that I can actually see the events in debug mode but I'm not sure how I can get the names of them.

Upvotes: 1

Views: 1286

Answers (1)

quadroid
quadroid

Reputation: 8940

You are right you where almost there, just the EventHandlerList is a linked list that is not easily itterated. You can take a look at the source code here: http://referencesource.microsoft.com/#System/compmod/system/componentmodel/EventHandlerList.cs

this will give you all Subscribed events of a Control(WinForms)

        EventHandlerList events = (EventHandlerList)typeof(Component)
               .GetField("events", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField)
               .GetValue(this);

        object current = events.GetType()
               .GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField)[0]
               .GetValue(events);

        List<Delegate> delegates = new List<Delegate>();
        while(current != null)
        {
            delegates.Add((Delegate)GetField(current,"handler"));
            current = GetField(current,"next");
        }

the static helper

        public static object GetField(object listItem, string fieldName)
        {
            return listItem.GetType()
               .GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField)
               .GetValue(listItem);
        }

Upvotes: 2

Related Questions