使用反射指定委托的类型(附加到事件)

本文关键字:事件 类型 反射 | 更新日期: 2023-09-27 17:58:19

我实际上想做的是这样的事情(我意识到这不是有效的代码):

// 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);
}
...

现在我知道e.EventHandlerType将始终从EventHandler<AutoWrapEventArgs>。然而,我不能只做:

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

作为。NET抱怨没有适用于EventHandler的转换<AutoWrapEventArgs>到EventHandler<DataEventArgs>当调用AddEventHandler时。这就是确切的信息:

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

我还尝试过使用Invoke来动态使用e.EventHandlerType的构造函数,但无法将委托定义传递给Invoke()的参数列表(因为没有从委托到对象的转换)。

有没有一种方法可以让我利用反思来解决这个问题?

使用反射指定委托的类型(附加到事件)

宾果!诀窍是获得对委托类型的构造函数的引用,然后使用以下参数调用它:

  • 委托的目标对象(backend.target)
  • 委托的指针(backend.Method.MethodHandle.GetFunctionPointer())

执行此操作的实际代码看起来像(本例中的t是在继承过程中提供给EventHandler<>的通用参数):

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

然后,您可以使用委托来添加事件,如下所示:

e.AddEventHandler(this, handler);

您可以使用Delegate.CreateDelegate来实现这样的目标:

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));
}