There is no simple method to achieve this.
Preferred Approach:
I do not understand why you cannot save the delegate. You do not need to save the instance as some field. It could be a local variable captured by your anonymous event handler:
EventHandler<TypeOfEventArgs> handler = null; handler = (s, e) => { // Do whatever you need to do here // Remove event: foo.Event -= handler; } foo.Event += handler;
I cannot imagine a single scenario where you cannot use this.
Alternative approach without saving the delegate:
However, if you have such a scenario, it becomes quite difficult.
You need to find the delegate that was added as the event handler. Since you did not save it, it is quite difficult to get it. There is no this to get the delegate of the current executable method.
You cannot use GetInvocationList() in an event, since access to the event outside the class in which it is defined is limited to adding and removing handlers, i.e. += and -= .
Creating a new delegate is also not possible. Although you can access the MethodInfo object that defines your anonymous method, you cannot access the instance of the class in which this method is declared. This class is automatically generated by the compiler and calling this inside the anonymous method will return an instance of the class in which your regular method is defined.
The only way I found work is to find the field - if there is one - this event uses and calls GetInvocationList() . The following code demonstrates this with a dummy class:
void Main() { var foo = new Foo(); foo.Bar += (s, e) => { Console.WriteLine("Executed"); var self = new StackFrame().GetMethod(); var eventField = foo.GetType() .GetField("Bar", BindingFlags.NonPublic | BindingFlags.Instance); if(eventField == null) return; var eventValue = eventField.GetValue(foo) as EventHandler; if(eventValue == null) return; var eventHandler = eventValue.GetInvocationList() .OfType<EventHandler>() .FirstOrDefault(x => x.Method == self) as EventHandler; if(eventHandler != null) foo.Bar -= eventHandler; }; foo.RaiseBar(); foo.RaiseBar(); } public class Foo { public event EventHandler Bar; public void RaiseBar() { var handler = Bar; if(handler != null) handler(this, EventArgs.Empty); } }
Note that the string "Bar" that is passed to GetField must be the exact name of the field used by the event. This leads to two problems:
- A field can be named differently, for example. when using an explicit implementation of the event. You need to manually find out the name of the field.
- There can be no field. This happens if the event uses an explicit implementation of the event and simply delegates to another event or saves the delegates in some other way.
Output:
An alternative approach depends on implementation details, so do not use it if you can avoid it.
Daniel Hilgarth
source share