2010-09-22 4 views
2

СВЯЗАННЫЕКак динамически подписаться на мероприятие?


Мне нужно, чтобы обнаружить, когда событие. Для этого я пытаюсь динамически подписываться на событие.

Проблема в том, что у меня есть разные типы делегатов, не все события имеют одну и ту же подпись. Решения, предоставленные in here и here, ожидают object sender, EventArgs e, которые я не использую, поэтому получаю исключение, указывающее, что типы не совпадают.

Вот некоторые примеры делегатов у меня есть:

public delegate void OnEventA(int id); 
public delegate void OnEventB(double num, string name); 

Как я могу создать правильный делегат?

ответ

2

После некоторых исследований я нашел несколько статей:

Это помогло мне понять, что я пытался сделать, и я должен делать.

мне нужно использовать Delegate.CreateDelegate прохождения EventHandlerType (типа события, делегат), экземпляр класса и информацию методы методы (из класса в предыдущем параметре), который будет обрабатывать событие. Цель - это элемент управления, который запускает это событие.

Delegate handler = Delegate.CreateDelegate(evt.EventHandlerType, abc, mi1, false); 
evt.AddEventHandler(target, handler); 

Дальнейшее копание приведет меня к этому методу. Я могу подписаться на события, используя лямбда-выражение. Использование Action<T> Я могу подписаться на разные типы и количество параметров.

public static Delegate Create<T>(EventInfo e, Action<T> a) 
{ 
    var parameters = e.EventHandlerType.GetMethod("Invoke").GetParameters().Select(p => Expression.Parameter(p.ParameterType, "p")).ToArray(); 
    var exp = Expression.Call(Expression.Constant(a), a.GetType().GetMethod("Invoke"), parameters); 
    var l = Expression.Lambda(exp, parameters); 
    return Delegate.CreateDelegate(e.EventHandlerType, l.Compile(), "Invoke", false); 
} 

Используя этот метод (е является EventInfo, EventManager класс со статическим методом выше)

e.AddEventHandler(this, EventManager.Create<int>(e, (x) => Console.WriteLine("Execute"))); 
6

EventInfo имеет способ AddEventHandler который вы можете использовать. Если вы не имеете экземпляр делегата, то вы можете создать делегат динамически с помощью Delegate.CreateDelegate:

var eh = Delegate.CreateDelegate(ei.EventHandlerType, target, methodInfo); 
ei.AddEventHandler(owner, eh); 

В этом примере target является целевым объектом для делегата и methodInfo является MethodInfo метода в target объекта , Наконец, owner - объект, к которому относится событие ei.

+0

мне нужно MethodInfo делать? Разве я не могу использовать лямбда? Что делать, если мне нужно передать параметры? – BrunoLM

+0

@BrunoLM: вы можете использовать лямбда вместо 'eh', если знаете тип делегата (например,« EventHandler »). Если вы этого не знаете, вам нужно создать новый экземпляр некоторого (вашего) объекта, использовать его вместо «target» и передать параметры этому объекту в конструкторе (в этом случае информация о методе будет инфо о некотором методе в этом объекте - вы можете, например,определите метод 'Invoke'). –

+0

Более конкретно: вы можете попробовать 'OnLoad eh =() => {...}'. Он будет работать до тех пор, пока все события 'Tickable' имеют тип делегата' OnLoad'. –

Смежные вопросы