Используя рефлексию, чтобы указать тип делегата (чтобы присоединиться к событию)? - PullRequest
3 голосов
/ 04 июня 2011

Что я действительно хочу сделать, это что-то вроде этого (я понимаю, что это не правильный код):

// 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 .Однако я не могу просто сделать:

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

    e.AddEventHandler(this, handler);

Поскольку .NET жалуется, что нет никакого преобразования, применимого от EventHandler к EventHandler , когда вызывается 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 () (потому чтонет преобразования из делегата в объект).

Есть ли способ, которым я могу использовать отражение , чтобы обойти эту проблему?

Ответы [ 2 ]

2 голосов
/ 05 июня 2011

Бинго! Хитрость заключается в том, чтобы получить ссылку на конструктор для типа делегата, а затем вызвать его, используя следующие параметры:

  • Целевой объект делегата (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);
0 голосов
/ 04 июня 2011

Вы можете использовать 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));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...