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.
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.
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.
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.
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.
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 });
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With