Есть ли способ узнать в VB.NET, если обработчик был зарегистрирован для события?

В С# я могу проверить это...

public event EventHandler Trigger;
protected void OnTrigger(EventArgs e)
{
    if (Trigger != null)
        Trigger(this, e);
}

Есть ли способ сделать это в VB.NET? Тест для null я означает?

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Я забыл упомянуть. У меня есть классы, написанные на С#, но я пишу свои модульные тесты в VB.NET.

Я пытаюсь это сделать в unit test...

If myObject.Trigger IsNot Nothing Then  
    ''#do something
End If

Это вызывает ошибку времени компиляции, которая говорит... "Trigger публичного события - это событие и не может быть вызвано напрямую. Используйте выражение RaiseEvent для создания события".

Сет

Ответ 1

В этом вопросе есть интересная дискуссия 1129517 о том, как это сделать на С#.

Так как класс, содержащий Событие, был написан на С#, семантика делегата действительно применяется, и эти методы должны работать на вас. Однако вам нужно перевести источник на VB.NET для вашего unit test.

Учитывая следующий класс в сборке С#:

public class Triggerific
{
    public event EventHandler Trigger;

    private static void OnTriggerTriggered(object sender, EventArgs e)
    {
        Console.WriteLine("Triggered!");
    }

    public void AddTrigger()
    {
        Trigger += OnTriggerTriggered;
    }
}

Вот некоторый код VB.NET, который будет правильно определять, был ли обработчик зарегистрирован для события Trigger:

<TestMethod()> _
Public Sub TriggerTest()
    Dim cut As New Triggerific
    cut.AddTrigger()

    Assert.IsNotNull(GetEventHandler(cut, "Trigger"))
End Sub

Private Shared Function GetEventHandler(ByVal classInstance As Object, ByVal eventName As String) As EventHandler
    Dim classType As Type = classInstance.[GetType]()
    Dim eventField As FieldInfo = classType.GetField(eventName, BindingFlags.GetField Or BindingFlags.NonPublic Or BindingFlags.Instance)

    Dim eventDelegate As EventHandler = DirectCast(eventField.GetValue(classInstance), EventHandler)

    ' eventDelegate will be null/Nothing if no listeners are attached to the event
    Return eventDelegate
End Function

Ответ 2

Да. null в Visual Basic называется "Nothing".

If Trigger IsNot Nothing Then

Update

В приведенном выше ответе описывается, как проверить что-то для null в VB.NET. К сожалению, события обрабатываются специальным компилятором VB.NET.

Для определения этого события:

Public Event Trigger as EventHandler

Вы использовали бы этот код для проверки подписки

If TriggerEvent Is Nothing

Обратите внимание, что VB.Net добавил поле с суффиксом Event для представления делегата. Имейте посмотрите здесь объяснение.

Ответ 3

Прежде всего, есть проблема с вашим кодом С#. Это должно выглядеть так, чтобы уменьшить вероятность условия гонки при удалении последнего обработчика в отдельном потоке в самое неподходящее время (намек на то, почему он работает: делегаты mulit-cast неизменны):

public event EventHandler Trigger;
protected void OnTrigger(EventArgs e)
{
    var temp = Trigger;
    if (temp != null)
        temp(this, e);
}

Во-вторых, нет необходимости в этом коде вообще в VB.Net. VB обрабатывает события несколько иначе, так что вы не должны вообще проверять, зарегистрированы ли какие-либо обработчики. Это безопасно и желательно просто поднять событие:

Public Event Trigger As EventHandler
Friend Sub OnTrigger(ByVal e As EventArgs)
    RaiseEvent Trigger(Me, e)
End Sub

Ответ 4

Я считаю, что синтаксис, который я использую для этого в VB.Net, это:

Public Event Trigger As EventHandler


Friend Sub OnTrigger(ByVal e As EventArgs)
    If TriggerEvent IsNot Nothing Then
        RaiseEvent Trigger(Me, e)
    End If
End Sub

Несмотря на то, что TriggerEvent не объявляется компилятором, он будет понимать его. Он ближе эмулирует синтаксис С#. Кроме того, я кое-что прочитал, что код с этим обработчиком asssigned check run fater, но я не могу указать на это на данный момент, поэтому вы можете взять или оставить это.

Я думаю, что это sytax, во всяком случае. Пожалуйста, не стреляйте в меня, если это не совсем правильно!

Ответ 5

У вас не должно быть проверки unit test, чтобы проверить, зарегистрирован ли обработчик. Как вы узнали, был ли он правильным обработчиком, или был ли он правильным обработчиком, но вел себя неправильно?

В чем смысл вашего теста?

Ответ 6

В VB.NET есть интересная языковая функция. Элемент-член создается для событий, которые предоставляют делегат:

Public Event MyEvent As EventHandler
Public Sub Test()

    Dim test = MyEventEvent
    Dim invokers = test.GetInvocationList()

End Sub

Фактически вы можете получить список вызовов.