Можно ли вызвать событие на объекте, извне этого объекта, без пользовательской функции
public class a
{
public event eventhandler test;
public void RaiseTest(){//fire test}
}
Можно ли поднять тест на этот класс, из-за пределов этого класса, без вызова метода?
В основном у меня есть большое количество событий, которые должны быть вызваны на основе внешнего источника, и я не хочу создавать функцию Raise() для каждого из них.
Можно ли создать универсальный Raise(), который принимает событие, которое будет вызвано в качестве параметра? поэтому он все равно будет вызываться изнутри класса?
2 ответа
Вы можете сделать это с помощью Reflection, но это менее чем очевидно. Если вы объявите событие в C#, в класс будет добавлено поле с именем события + "Событие". Если вы вызовете GetValue для поля, он вернет экземпляр MulticastDelegate.
Получив MulticastDelegate, вы можете получить список вызовов и вызывать каждого участника по очереди:
EventArgs e = new EventArgs(myClassInstance); // Create appropriate EventArgs
MulticastDelegate eventDelagate =
this.GetType().GetField(theEventName + "Event",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).GetValue(myClassInstance) as MulticastDelegate;
Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate del in delegates) {
del.Method.Invoke(del.Target, new object[] { myClassInstance, e });
}
Обратите внимание, что для этого необходимо получить поле NonPublic из экземпляра, поэтому оно будет работать только с полным доверием и очень ограничено.
Можно ли создать универсальный Raise(), который принимает событие, которое будет вызвано в качестве параметра? поэтому он все равно будет вызываться изнутри класса?
Да. Было бы довольно легко изменить приведенный выше код, чтобы сделать это. Просто замените "myClassInstance" этим. На самом деле это также позволит работать должным образом с полным доверием, поскольку NonPublic BindingFlag больше не будет проблемой.
Можно ли поднять тест на этот класс, из-за пределов этого класса, без вызова метода?
Краткий ответ: нет.
Только класс, объявляющий событие, может поднять его
Можно ли создать универсальный Raise(), который принимает событие, которое будет вызвано в качестве параметра? поэтому он все равно будет вызываться изнутри класса?
Я так не думаю, по крайней мере, не легко... Даже используя отражение, нет EventInfo.Invoke
метод. AFAIK, единственный способ поднять событие статически из класса
РЕДАКТИРОВАТЬ: на самом деле это может быть сделано (см. Ответ Рида), но с ограничением, что приложение должно работать в полном доверии.