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

C# 有没有办法在VB.NET中知道是否已为事件注册了处理程序?,c#,.net,vb.net,events,null,C#,.net,Vb.net,Events,Null,在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

在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语句引发事件。”

赛斯是的。null在Visual Basic中称为“Nothing”

If Trigger IsNot Nothing Then
更新 上面的答案描述了如何在VB.NET中检查空值。不幸的是,事件由VB.NET编译器进行特殊处理

对于此事件定义:

Public Event Trigger as EventHandler
您可以使用此代码检查订阅

If TriggerEvent Is Nothing

请注意VB.Net如何添加一个后缀为
Event
的字段来表示委托。首先,你的c代码有问题。它应该这样读,以减少在错误的时间删除单独线程中的最后一个处理程序时出现争用情况的可能性(关于其工作原理的提示:mulit cast委托是不可变的):

其次,在VB.Net中根本不需要这个代码。VB处理事件的方式稍有不同,因此您根本不应该检查是否注册了任何处理程序。这是安全的,最好只是提出事件:

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

您不应该使用单元测试来检查处理程序是否已注册。您如何知道它是否是正确的处理程序,或者它是否是正确的处理程序但行为不正确


你测试的目的是什么?

关于如何在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代码,可以正确确定是否为触发器事件注册了处理程序:

<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
_
公共子触发器测试()
暗切为新触发器
cut.AddTrigger()
IsNotNull(GetEventHandler(剪切,“触发器”))
端接头
私有共享函数GetEventHandler(ByVal classInstance作为对象,ByVal eventName作为字符串)作为EventHandler
Dim classType As Type=classInstance。[GetType]()
将eventField设置为FieldInfo=classType.GetField(eventName、BindingFlags.GetField或BindingFlags.NonPublic或BindingFlags.Instance)
Dim eventDelegate作为EventHandler=DirectCast(eventField.GetValue(classInstance),EventHandler)
'如果没有侦听器附加到事件,则eventDelegate将为null/Nothing
返回事件委托
端函数

我相信我在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看起来没有声明,编译器也会理解它。它更接近于模拟C#语法。另外,我在这里读到过一些关于这个处理程序作为签名检查的代码运行更慢的消息,但是我现在不能指出这一点,所以你可以接受或离开它


无论如何,我想那是sytax。如果不太正确,请不要开枪

VB.NET中有一个有趣的语言“功能”。为公开委托的事件创建成员变量:

Public Event MyEvent As EventHandler
Public Sub Test()

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

End Sub

实际上,您可以通过这种方式获得调用列表。

Joel。。。谢谢你的回复。我将更新我的代码。请看我问题的更新(这是我第一次学习C#项目)。在我的例子中,我正在编写一个单元测试,该测试正在检查以验证是否有处理程序为事件注册。但我认为从你的答案来看,在vb.net.PS中没有办法做到这一点……我的观点是我不知道“我不想提起这件事。我确实想检查它是否为空,因为这就是我进行单元测试的目的。SethI确实回答了下面的问题。不过,我也建议您应该测试的是注册一个事件处理程序,而不是登记它(因为这将是测试已经被测试的CLR功能)。更具体地,考虑使用一个更容易的框架,或者。如果你看我的问题,你会发现触发器不是什么都不会导致vb.net中的编译错误。我忘了在我的问题中提到这一点,你回答得太快了,以至于在我更新问题之前你就回答了。底线…是您的代码导致编译错误。Seth@Seth斯皮尔曼:这样做吧:如果TriggerEvent不是什么都没有,那就对了@JJS null什么都不怕,不可能,也不怎么害怕。约翰,谢谢你的回答。它拍得很好。我正在做一个“学习”项目,我正在自学C#和单元测试。我想我采用的方法是使用单元测试来定义api。因此,我的类中有一个测试调用AddTrigger的方法。它将向该集合中添加一个对象,同时在该对象中注册一个触发器。我真的在为测试什么和不测试什么而挣扎。我意识到测试.NET或任何其他外部库都没有意义。但是再一次…安装/拆卸只定义了一个触发器寄存器。所以。。。继续…我有两种测试方法。。。AddTrigger\u TriggerNotExists\u TriggerAdded()。。。AddTrigger\u TriggerNotExists\u EventRegistered()。。。测试第一个很简单…只需验证是否已将项添加到集合中。它似乎确保代码..不管它是什么..将验证触发器事件是否已注册。但也许不是。Sethhemp…谢谢你的回答和你的建议,这更适合嘲笑。我的日程安排是学习犀牛模仿。塞思那真是太棒了。它不起作用。事件不是VB.NET中的字段。这只作为C#代码的VB.NET测试方法使用,在这种情况下,它是毫无意义的。。。但是,如果你不小心的话,它是有效的
Public Event MyEvent As EventHandler
Public Sub Test()

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

End Sub