Подписка действия на любой тип события через отражение - PullRequest
11 голосов
/ 18 марта 2012

Рассмотрим:

someControl.Click += delegate { Foo(); };

Аргументы события не имеют значения, они мне не нужны, и они меня не интересуют.Я просто хочу, чтобы Foo () был вызван.Нет очевидного способа сделать то же самое с помощью отражения.

Я бы хотел перевести вышесказанное во что-то вроде

void Foo() { /* launch missiles etc */ }

void Bar(object obj, EventInfo info)
{
    Action callFoo = Foo;
    info.AddEventHandler(obj, callFoo);
}

Также я не хочуПредположение, что тип объекта, передаваемый в Bar, строго соответствует правилам использования сигнатуры EventHander (TArgs) для событий.Проще говоря, я ищу способ подписать Action для любого типа обработчика;не так просто, способ преобразовать делегат Action в делегат ожидаемого типа обработчика.

Ответы [ 2 ]

8 голосов
/ 18 марта 2012
static void AddEventHandler(EventInfo eventInfo, object item,  Action action)
{
  var parameters = eventInfo.EventHandlerType
    .GetMethod("Invoke")
    .GetParameters()
    .Select(parameter => Expression.Parameter(parameter.ParameterType))
    .ToArray();

  var handler = Expression.Lambda(
      eventInfo.EventHandlerType, 
      Expression.Call(Expression.Constant(action), "Invoke", Type.EmptyTypes), 
      parameters
    )
    .Compile();

  eventInfo.AddEventHandler(item, handler);
}
static void AddEventHandler(EventInfo eventInfo, object item, Action<object, EventArgs> action)
{
  var parameters = eventInfo.EventHandlerType
    .GetMethod("Invoke")
    .GetParameters()
    .Select(parameter => Expression.Parameter(parameter.ParameterType))
    .ToArray();

  var invoke = action.GetType().GetMethod("Invoke");

  var handler = Expression.Lambda(
      eventInfo.EventHandlerType,
      Expression.Call(Expression.Constant(action), invoke, parameters[0], parameters[1]),
      parameters
    )
    .Compile();

  eventInfo.AddEventHandler(item, handler);
}

Использование:

  Action action = () => BM_21_Grad.LaunchMissle();

  foreach (var eventInfo in form.GetType().GetEvents())
  {
    AddEventHandler(eventInfo, form, action);
  }
0 голосов
/ 18 марта 2012

Как насчет этого?

void Bar(object obj, EventInfo info)
{
    var parameters = info.EventHandlerType.GetMethod("Invoke").GetParameters()
        .Select(p => Expression.Parameter(p.ParameterType));

    var handler = Expression.Lambda(
        info.EventHandlerType,
        Expression.Call(
            Expression.Constant(obj), // obj is the instance on which Foo()
            "Foo",                    // will be called
            null
        ),
        parameters
    );
    info.AddEventHandler(obj, handler.Compile());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...