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

时间:2011-06-04 01:18:40

标签: c# events reflection .net-3.5 delegates

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

// 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&lt; AutoWrapEventArgs&gt;的转换。到EventHandler&lt; DataEventArgs&gt;调用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()的参数列表(因为没有从委托到对象的转换)。

我有没有办法reflection来解决这个问题?

2 个答案:

答案 0 :(得分:2)

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

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

执行此操作的实际代码(在这种情况下,t是在继承期间提供给EventHandler&lt;&gt;的通用参数):

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

答案 1 :(得分:0)

您可以使用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));
}