Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manually invoke an event?

Tags:

c#

events

I have the following line in C#:

_timer.ElapsedTick += _somefunction1; _timer.ElapsedTick += _somefunction2; _timer.ElapsedTick += _somefunction3; 

How to invoke all methods subscribed to _timer.ElapsedTick without specifying the _somefunction ? Somewhere along this pseudo-line

invoke(_timer.ElapsedTick); 
like image 417
Jeson Martajaya Avatar asked Jan 04 '12 22:01

Jeson Martajaya


People also ask

How do you invoke an event?

You need to first get the field that represents the event on the type as a MulticastDelegate , then get its invocationlist and from there you can dynamically invoke each method individually. The answer to this MSDN question shows how to do it.

How do I call an event in C#?

If you REALLY need to call an event manually, you can get the backing delegate, which is usually private. Use a . NET decompiler (such as ILSPY) to locate the Event's backing field, then use reflection to get the backing delegate. So you need to find the Events member, and the doWorkKey field as a key.

What is EventArgs C#?

EventArgs is also the class you use when an event does not have any data associated with it. When you create an event that is only meant to notify other classes that something happened and does not need to pass any data, include the EventArgs class as the second parameter in the delegate. You can pass the EventArgs.

Can we use events without delegates?

Yes, you can declare an event without declaring a delegate by using Action. Action is in the System namespace.


2 Answers

You can't invoke an event which is owned by another type. An event can only be invoked from the inside the class which declares it.

like image 153
JaredPar Avatar answered Sep 21 '22 23:09

JaredPar


Can it be done using conventional C#? No (as previously stated). But using reflection it is possible. Here is some tested code based on the answer to this MSDN forum thread:

class InvokeFromMe {     public event EventHandler RaiseMe; }  class Program {     static void Main(string[] args)     {         var fromMe = new InvokeFromMe();          fromMe.RaiseMe += fromMe_RaiseMe;         fromMe.RaiseMe += fromMe_RaiseMe1;         fromMe.RaiseMe += fromMe_RaiseMe2;          FireEvent(fromMe, "RaiseMe", null, EventArgs.Empty);     }      static void fromMe_RaiseMe(object sender, EventArgs e)     {         Console.WriteLine("Event Handler 0 Raised");     }     static void fromMe_RaiseMe1(object sender, EventArgs e)     {         Console.WriteLine("Event Handler 1 Raised");     }     static void fromMe_RaiseMe2(object sender, EventArgs e)     {         Console.WriteLine("Event Handler 2 Raised");     }      public static void FireEvent(object onMe, string invokeMe, params object[] eventParams)     {         MulticastDelegate eventDelagate =               (MulticastDelegate)onMe.GetType().GetField(invokeMe,                System.Reflection.BindingFlags.Instance |                System.Reflection.BindingFlags.NonPublic).GetValue(onMe);          Delegate[] delegates = eventDelagate.GetInvocationList();          foreach (Delegate dlg in delegates)         {             dlg.Method.Invoke(dlg.Target, eventParams);         }     }   } 

UPDATE

I'm not familiar with the System.Timer.Timer class, so I'm not sure what is different from my provided example. You could perhaps try something like:

public static void FirePublicEvent(object onMe, string invokeMe, params object[] eventParams) {     MulticastDelegate eventDelagate =           (MulticastDelegate)onMe.GetType().GetField(invokeMe,            System.Reflection.BindingFlags.Instance |            System.Reflection.BindingFlags.Public).GetValue(onMe);      Delegate[] delegates = eventDelagate.GetInvocationList();      foreach (Delegate dlg in delegates)     {        dlg.Method.Invoke(dlg.Target, eventParams);     } }  
like image 24
M.Babcock Avatar answered Sep 18 '22 23:09

M.Babcock