Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting event via reflection

Tags:

c#

reflection

Iam trying to get the Click event of a button via reflection and this is my code :

Assembly assem = Assembly.GetExecutingAssembly();

Type tExForm = btnSave.GetType();
Object exFormAsObj = Activator.CreateInstance(tExForm);

EventInfo evClick = tExForm.GetEvent("Click");
Type tDelegate = evClick.EventHandlerType;

MethodInfo miHandler=
btnSave.GetType().GetMethod("Click",
BindingFlags.NonPublic | BindingFlags.Instance);

Delegate d = Delegate.CreateDelegate(tDelegate, btnSave, miHandler);

MethodInfo addHandler = evClick.GetAddMethod();
Object[] addHandlerArgs = { d };
addHandler.Invoke(exFormAsObj, addHandlerArgs);

However the miHandler variable is always null!

Note The main issue I am concerned in is how to invoke an event of a specific control at run time, is there a way? For example I want to choose which click event to trigger when the user presses F1.

like image 341
Hasan Shouman Avatar asked May 09 '14 15:05

Hasan Shouman


People also ask

How do I get the method that handles an event?

Get a MethodInfo object representing the method that handles the event. The complete program code in the Example section later in this topic contains a method that matches the signature of the EventHandler delegate, which handles the Click event, but you can also generate dynamic methods at run time.

How do I create an event handler for a form?

Clicking the form invokes the event handler. Event-handler methods can be generated at run time, using lightweight dynamic methods and reflection emit. To construct an event handler, you need the return type and parameter types of the delegate. These can be obtained by examining the delegate's Invoke method.

How do I get an eventinfo for the click event?

Get an EventInfo object representing the event, and use the EventHandlerType property to get the type of delegate used to handle the event. In the following code, an EventInfo for the Click event is obtained.

Is reflection brittle?

That having been said, here's how to do it. Reflection is always brittle, and this is a prime example of it - you have to rely on the current implementation details of how events in .NET work, which could change tomorrow, and this will stop working.


1 Answers

Based on additional comments below the question, the real goal is to raise an event via reflection.

I'll start by saying this is almost guaranteed to be a really terrible idea. It's going to be error-prone and brittle; it's just asking for bugs. What I'd recommend instead is having many event handlers (button click handler, keypress event handler, etc.) all simply call a common method which does the actual thing you want.

That having been said, here's how to do it. Reflection is always brittle, and this is a prime example of it - you have to rely on the current implementation details of how events in .NET work, which could change tomorrow, and this will stop working. You get a private field stored on the object which holds references to all the subscribing event handlers, loop through each one and invoke it. You also need to manually create the arguments that will be passed (like the EventArgs):

var eventArgs = EventArgs.Empty; //replace with real args

var eventInfo = tExForm.GetType().GetEvent("Click", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var eventDelegate = (MulticastDelegate)tExForm.GetType().GetField("Click", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tExForm);
if (eventDelegate != null)
{
  foreach (var handler in eventDelegate.GetInvocationList())
  {
    handler.Method.Invoke(handler.Target, new object[] { tExForm, eventArgs });
  }
}
like image 95
Rex M Avatar answered Oct 04 '22 00:10

Rex M