Is it possible to raise an event on an object, from outside that object, without a custom function

StackOverflow https://stackoverflow.com/questions/1230223

  •  22-07-2019
  •  | 
  •  

Question

public class a
{
   public event eventhandler test;
   public void  RaiseTest(){//fire test}
}

Is it possible to raise test on this class, from outside this class, without calling the method?

Basically I have a large number of events which must be raised based on an external source, and do not want to create a Raise() function for each one.

Is it possible to create a generic Raise() that accepts the event to be raised as a parameter? therefore it would still be called from inside the class?

Was it helpful?

Solution

You can do this via Reflection, but it is less than obvious. If you declare an event in C#, a field will be added to the class with the event name + "Event". If you call GetValue on the field, it will return a MulticastDelegate instance.

Once you have the MulticastDelegate, you can get the invocation list, and invoke each member in turn:

EventArgs e = new EventArgs(myClassInstance);  // Create appropriate EventArgs

MulticastDelegate eventDelagate = 
    this.GetType().GetField(theEventName + "Event",
    System.Reflection.BindingFlags.Instance | 
    System.Reflection.BindingFlags.NonPublic).GetValue(myClassInstance) as MulticastDelegate;

Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate del in delegates) {  
      del.Method.Invoke(del.Target, new object[] { myClassInstance, e }); 
}

Note that this requires getting a NonPublic field from the instance, so it will only work in full trust, and is very limited.

Is it possible to create a generic Raise() that accepts the event to be raised as a parameter? therefore it would still be called from inside the class?

Yes. It would be fairly easy to modify the above code to do this. Just replace "myClassInstance" with this. This will actually allow this to work properly in full trust, as well, since the NonPublic BindingFlag will no longer be an issue.

OTHER TIPS

Is it possible to raise test on this class, from outside this class, without calling the method?

Short answer : no.

Only the class declaring the event can raise it

Is it possible to create a generic Raise() that accepts the event to be raised as a parameter? therefore it would still be called from inside the class?

I don't think so, at least not easily... Even using reflection, there is no EventInfo.Invoke method. AFAIK, the only way to raise the event is statically from within the class

EDIT: actually it can be done (see Reed's answer), but with the limitation that the app has to run in full trust.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top