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

В C# я могу протестировать на это...

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

Существует ли способ сделать это в VB.NET? Тест для пустого указателя я имею в виду?

Подробнее

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

Я пробую это в модульном тесте...

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

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

Seth

11
задан Joel Coehoorn 1 June 2010 в 19:23
поделиться

4 ответа

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

Поскольку класс, содержащий событие, был написан на C#, семантика делегата действительно применима, и эти методы должны сработать для вас. Однако для модульного теста вам нужно будет перевести исходный текст на VB.NET.

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

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
8
ответ дан 3 December 2019 в 02:19
поделиться

Во-первых, есть проблема с вашим кодом на c#. Он должен выглядеть так, чтобы уменьшить вероятность возникновения состояния гонки при удалении последнего обработчика в отдельном потоке в самый неподходящий момент (подсказка, почему это работает: 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
9
ответ дан 3 December 2019 в 02:19
поделиться

Вы не должны использовать модульный тест, проверяющий, зарегистрирован ли обработчик. Как вы узнаете, является ли он правильным обработчиком, или это правильный обработчик, но ведет себя неправильно?

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

1
ответ дан 3 December 2019 в 02:19
поделиться

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

If Trigger IsNot Nothing Then

Обновить

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

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

Public Event Trigger as EventHandler

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

If TriggerEvent Is Nothing

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

11
ответ дан 3 December 2019 в 02:19
поделиться