Is there a way to know in VB.NET if a handler has been registered for an event?

前端 未结 6 1237
难免孤独
难免孤独 2021-01-17 14:07

In C# I can test for this...

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


        
相关标签:
6条回答
  • 2021-01-17 14:23

    Yes. null is called "Nothing" in Visual Basic.

    If Trigger IsNot Nothing Then
    

    Update

    The above answer describes how to check something for null in VB .NET. Unfortunately, events are handled special by the VB.NET compiler.

    For this event definition:

    Public Event Trigger as EventHandler
    

    You would use this code to check for subscriptions

    If TriggerEvent Is Nothing
    

    Notice how VB.Net added a field with the suffix Event to represent the delegate. Have a look here for an explanation.

    0 讨论(0)
  • 2021-01-17 14:28

    There is an interesting discussion in question 1129517 around how to do this very thing in C#.

    Since the class that contains the Event was written in C#, the delegate semantics do apply, and those techniques should work for you. However, you'll need to translate the source to VB.NET for your unit test.

    Given the following class in a C# assembly:

    public class Triggerific
    {
        public event EventHandler Trigger;
    
        private static void OnTriggerTriggered(object sender, EventArgs e)
        {
            Console.WriteLine("Triggered!");
        }
    
        public void AddTrigger()
        {
            Trigger += OnTriggerTriggered;
        }
    }
    

    Here is some VB.NET code which will correctly determine if a handler was registered for the Trigger event:

    <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
    
    0 讨论(0)
  • 2021-01-17 14:28

    I believe the syntax I use for this in VB.Net is:

    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
    

    Even though TriggerEvent does not appear to be declared the compiler will understand it.It closer emulates the C# syntax. Also I have read somehere that the code with that handler asssigned check runs fater, but I cannot point to that at the moment, so youcan take or leave that.

    I think that is the sytax, anyway. Please dont shoot me if it is not quite correct!

    0 讨论(0)
  • 2021-01-17 14:41

    First of all, there's a problem with your c# code. It should read like this to reduce the likelihood of a race condition on removing the last handler in a separate thread at just the wrong time (hint on why it works: mulit-cast delegates are immutable):

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

    Secondly, there's no need for this code at all in VB.Net. VB handles events a little differently, such that you should not check at all whether any handlers are registered. It's safe and preferred to just raise the event:

    Public Event Trigger As EventHandler
    Friend Sub OnTrigger(ByVal e As EventArgs)
        RaiseEvent Trigger(Me, e)
    End Sub
    
    0 讨论(0)
  • 2021-01-17 14:42

    You should not have a unit test checking to see if a handler is registered. How would you know whether it was the correct handler, or if it was the correct handler but was behaving incorrectly?

    What is the point of your test?

    0 讨论(0)
  • 2021-01-17 14:46

    There's an interesting language "feature" in VB .NET. A member variable is created for events that exposes the delegate:

    Public Event MyEvent As EventHandler
    Public Sub Test()
    
        Dim test = MyEventEvent
        Dim invokers = test.GetInvocationList()
    
    End Sub
    

    You can actually get the invocation list this way.

    0 讨论(0)
提交回复
热议问题