i am attempting to attach a Delegate to an invocation list of a different delegate. By that i am achieving a kind of Hook on existing events. I need to hook up something that runs after each event that is invoked.
The following example works as long as the Delegate exposed by the type and the Action i pass in have the exact same signature. (On1 and OnAll events are both declared with an Action delegate so it works).
Code : How i hook up an Action with an existing delegate exposed by an event modifier.
public static class ReflectionExtensions
{
public static IEnumerable<EventInfo> GetEvents(this object obj)
{
var events = obj.GetType().GetEvents();
return events;
}
public static void AddHandler(this object obj, Action action)
{
var events = obj.GetEvents();
foreach (var @event in events)
{
@event.AddEventHandler(obj, action);
}
}
}
The Sample :
public class Tester
{
public event Action On1;
public event Action On2;
public void RaiseOn1()
{
On1();
}
public void RaiseOn2()
{
On2();
}
}
class Program
{
static void Main(string[] args)
{
var t = new Tester();
t.On1 += On1;
t.On2 += On2;
t.AddHandler(OnAll);
t.RaiseOn1();
t.RaiseOn2();
}
public void On1() { }
public void On2() { }
public void OnAll() { }
}
The Problem : When the Delegate exposed with an event modifier in Tester does not have the same signature i get a well wanted and obvious exception which states (in my words) that Action
can't be added to an invocation list of an Action<int>
. makes sense.
Just to be clear I'm describing the following :
public event Action<int> On1;
public void On1(int i){}
What I'm looking for is a way to create another Delegate of the same type as the EventHandlerType. In order to do that i need to create a method with the signature i of EventHandlerType which would internally invoke action.
something like :
public static void AddHandler(this object obj, Action action)
{
var events = obj.GetEvents();
foreach (var @event in events)
{
// method with the signeture of EventHandlerType which does action();
MethodInfo wrapperMethod = WrapAction(@event.EventHandlerType, action);
Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, wrapperMethod);
@event.AddEventHandler(obj, handler);
}
}