简体   繁体   English

有没有办法在VB.NET中知道是否为事件注册了处理程序?

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

In C# I can test for this... 在C#中,我可以测试一下......

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

Is there a way to do this in VB.NET? 有没有办法在VB.NET中执行此操作? Test for null I mean? 测试null我的意思是?

MORE INFO 更多信息

I forgot to mention. 我忘了提。 I have classes written in C# but I am writing my unit tests in VB.NET. 我有用C#编写的类,但我在VB.NET中编写单元测试。

I am trying this in the unit test... 我在单元测试中尝试这个...

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

This is causing a compile time error which says ... "Public Event Trigger is an Event and cannot be called directly. Use the RaiseEvent statement to raise an event." 这导致编译时错误,表示“公共事件触发器是一个事件,无法直接调用。使用RaiseEvent语句引发事件。”

Seth 赛斯

Yes. 是。 null is called "Nothing" in Visual Basic. null在Visual Basic中称为“Nothing”。

If Trigger IsNot Nothing Then

Update 更新

The above answer describes how to check something for null in VB .NET. 上面的答案描述了如何在VB .NET中检查null的内容。 Unfortunately, events are handled special by the VB.NET compiler. 不幸的是,事件由VB.NET编译器处理。

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. 请注意VB.Net如何添加带有后缀Event的字段来表示委托。 Have a look here for an explanation . 看看这里的解释

First of all, there's a problem with your c# code. 首先,你的c#代码存在问题。 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): 它应该像这样读取,以减少在错误的时间删除单独线程中的最后一个处理程序的竞争条件的可能性(提示它为什么工作:mulit-cast委托是不可变的):

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.Net中根本不需要这个代码。 VB handles events a little differently, such that you should not check at all whether any handlers are registered. VB处理事件的方式略有不同,因此您根本不应检查是否已注册任何处理程序。 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

There is an interesting discussion in question 1129517 around how to do this very thing in C#. 关于如何在C#中执行此操作,问题1129517中有一个有趣的讨论。

Since the class that contains the Event was written in C#, the delegate semantics do apply, and those techniques should work for you. 由于包含Event的类是用C#编写的,因此委托语义确实适用,这些技术应该适合您。 However, you'll need to translate the source to VB.NET for your unit test. 但是,您需要将源代码转换为VB.NET以进行单元测试。

Given the following class in a C# assembly: 给定C#程序集中的以下类:

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: 这是一些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

I believe the syntax I use for this in VB.Net is: 我相信我在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

Even though TriggerEvent does not appear to be declared the compiler will understand it.It closer emulates the C# syntax. 即使TriggerEvent似乎没有声明,编译器也会理解它。它更接近模拟C#语法。 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. 无论如何,我认为这就是sytax。 Please dont shoot me if it is not quite correct! 如果不太正确,请不要开枪!

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? 你的测试有什么意义?

There's an interesting language "feature" in VB .NET. 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. 您实际上可以通过这种方式获取调用列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM