Using reflection to indicate the type of delegate (to attach to an event)?

What I really want to do is something like this (I understand that this is invalid code):

// Attach the event. try { EventInfo e = mappings[name]; (e.EventHandlerType) handler = (sender, raw) => { AutoWrapEventArgs args = raw as AutoWrapEventArgs; func.Call(this, args.GetParameters()); }; e.AddEventHandler(this, handler); } ... 

Now I know that e.EventHandlerType will always output from EventHandler <AutoWrapEventArgs>. However, I cannot just do:

  EventHandler<AutoWrapEventArgs> handler = (sender, raw) => { AutoWrapEventArgs args = raw as AutoWrapEventArgs; func.Call(this, args.GetParameters()); }; e.AddEventHandler(this, handler); 

Because .NET complains that there is no conversion applicable in EventHandler <AutoWrapEventArgs> to EventHandler <DataEventArgs> when AddEventHandler is called. This is the exact message:

 Object of type 'System.EventHandler`1[IronJS.AutoWrapObject+AutoWrapEventArgs]' cannot be converted to type 'System.EventHandler`1[Node.net.Modules.Streams.NodeStream+DataEventArgs]'. 

I also tried using Invoke to dynamically use the e.EventHandlerType constructor, but there is no way to pass the delegate definition to the Invoke () parameter list (because there is no conversion from delegate to object).

Can reflection be used to get around this?

+3
reflection c # events delegates
source share
2 answers

Bingo! The trick is to get a constructor reference for the delegate type, and then call it using the following parameters:

  • Delegate Target (backend.Target)
  • Delegate Pointer (backend.Method.MethodHandle.GetFunctionPointer ())

The actual code that does this looks like (t in this case is the general argument provided by EventHandler <> during inheritance):

 Type t = e.EventHandler.GetGenericArguments()[0]; Delegate handler = (Delegate) typeof(EventHandler<>) .MakeGenericType(t) .GetConstructors()[0] .Invoke(new object[] { backend.Target, backend.Method.MethodHandle.GetFunctionPointer() }); 

Then you can use the delegate to add the event like this:

 e.AddEventHandler(this, handler); 
+1
source share

You can use Delegate.CreateDelegate to achieve your goal as follows:

 public void RegisterHandler(string name) { EventInfo e = mappings[name]; EventHandler<AutoWrapEventArgs> handler = (s, raw) => { func.Call(this, raw.GetParameters()); }; e.AddEventHandler(this, Delegate.CreateDelegate(e.EventHandlerType, null, handler.Method)); } 
0
source share

All Articles