GetInvocationList события в VB.NET
Я пытаюсь изучить некоторые принципы WCF, следуя примеру приложения WCF (от Sacha Barber).
Теперь я хотел бы преобразовать следующую функцию в VB.NET
private void BroadcastMessage(ChatEventArgs e)
{
ChatEventHandler temp = ChatEvent;
if (temp != null)
{
foreach (ChatEventHandler handler in temp.GetInvocationList())
{
handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
}
}
}
Но у меня есть некоторые проблемы, потому что следующий код не принимается компилятором
Private Sub BroadcastMessage(ByVal e As ChatEventArgs)
Dim handlers As EventHandler(Of ChatEventArgs) = ChatEvent
If handlers IsNot Nothing Then
For Each handler As EventHandler(Of ChatEventArgs) In handlers.GetInvocationList()
handler.BeginInvoke(Me, e, New AsyncCallback(AddressOf EndAsync), Nothing)
Next
End If
End Sub
Там написано
Общедоступное общее событие ChatEvent (отправитель
Как объект, как ChatEventArgs) - это
событие, и не может быть вызвано непосредственно
Переходим к сути, возможно ли тогда в VB.NET связать обработчики с определенным событием каким-то другим способом?
2 ответов:
Использовать ChatEventEvent (или Имя_событияСобытие)
Он не будет отображаться в intellisense, но его члены будут.
VB.NET создает переменную за кулисами, чтобы скрыть сложность от верстальщика...
Это доступно только в классе, который объявляет событие (или, возможно, его потомков)
Вероятно, вы пытаетесь написать этот код в классе, который является потомком класса, объявляющего событие
ChatEvent. Это невозможно, так как события могут рассматриваться только как переменные (включая их вызов) в классе, который их объявляет. Это происходит потому, что ключевое словоeventфактически указывает компилятору, что ему необходимо выполнить некоторые закулисные преобразования.Что Происходит
Рассмотрим следующее заявление:
Public Event MyEvent as EventHandlerДостаточно просто, так ведь? Однако на самом деле это делает вот что (вы просто не видите этого)
Private compilerGeneratedName as EventHandler Public Event MyEvent as EventHandler AddHandler(ByVal value as EventHandler) compilerGeneratedName += value End AddHandler RemoveHandler(ByVal value as EventHandler) compilerGeneratedName -= value End RemoveHandler RaiseEvent(ByVal sender as Object, ByVal e as EventArgs) compilerGeneratedName.Invoke(sender, e) End RaiseEvent End EventИ когда вы вызываете событие:
RaiseEvent MyEvent(Me, EventArgs.Emtpy)Он фактически вызывает код в блоке
RaiseEvent.Edit
Если события в VB.NET не могут быть обработаны как переменные в любом месте (они могут быть обработаны как переменные в объявлении класса В C#, поэтому ваш пример C# компилируется), то вам придется явно реализовать событие самостоятельно. Смотрите страницу MSDN на оператор события для получения дополнительной информации о том, как это сделать. Короче говоря, вам понадобится какой-то способ хранения нескольких обработчиков событий (или использовать один обработчик событий вместе с
GetInvocationList, как вы пытаетесь сделать сейчас). В ваших блоках кодаAddHandlerиRemoveHandlerвы будете добавлять и удалять из списка обработчиков событий (соответственно).Вы могли бы использовать что-то вроде этого:
Private myEventList as New List(Of EventHandler) Public Custom Event MyEvent as EventHandler AddHandler(ByVal value as EventHandler) myEventList.Add(value) End AddHandler RemoveHandler(ByVal value as EventHandler) myEventList.Remove(value) End RemoveHandler RaiseEvent(ByVal sender as Object, ByVal e as EventArgs) For Each evt in myEventList evt.BeginInvoke(sender, e, New AsyncCallback(AddressOf EndAsync), Nothing) Next EndRaiseEvent End EventТак что теперь, если вы позвоните
RaiseEvent MyEvent(Me, EventArgs.Emtpy)Это поднимет событие в моде, которую вы ожидающий.
Comments