是否有可能在 VB.Net 的多项目解决方案中引发全局事件。例如,项目 1 有一个名为 Form1 的窗体。在 Form1 上有一个按钮,单击该按钮会引发一个事件,project2 可以在其中处理该事件,甚至 project3 也可以处理该事件。
2 回答
你可以有一个专门的项目,它有一个类,其唯一目的是容纳一个“全球事件”。使该类实现单例模式,以便所有项目都可以访问同一个实例。所有其他项目都可以引用此项目,并且可能如下所示:
' This is in Project3
Public Class Class1
Private Sub New()
End Sub
Private Shared _Instance As Class1
Public Event GlobalEvent()
Public Shared ReadOnly Property Instance As Class1
Get
If IsNothing(_Instance) Then
_Instance = New Class1
End If
Return _Instance
End Get
End Property
Public Sub RingTheBell()
RaiseEvent GlobalEvent()
End Sub
End Class
这是Project1中的FormA,在Project2中显示FormB(Project1同时引用了Project2和Project3)。我们获取单例实例并调用 RingTheBell() 方法来引发“全局事件”:
' This is in Project1
Public Class FormA
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim frmB As New Project2.FormB
frmB.Show()
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Project3.Class1.Instance.RingTheBell()
End Sub
End Class
最后,在 Project2 中,我们还获取了单例实例并订阅了它的 GlobalEvent(Project2 仅引用了 Project3):
' This is in Project2
Public Class FormB
Private WithEvents x As Project3.Class1 = Project3.Class1.Instance
Private Sub x_GlobalEvent() Handles x.GlobalEvent
MessageBox.Show("GlobalEvent() trapped in Project2")
End Sub
End Class
因此,任何想要订阅“全局事件”的项目只需添加对 Project3 的引用并使用 Instance() 方法返回该项目可以订阅事件的单例实例。
这可以通过许多可能的途径实现。在这种情况下,我更喜欢依赖注入。
首先,创建您的全球活动所有者项目。我将我的命名为 GlobalEventSample。我删除了默认命名空间并在此处显式声明以使代码结构更加明显:
Namespace GlobalEventSample
Public Module Module1
Public Event GlobalEvent As EventHandler
Public Sub Main()
Console.WriteLine("Press any key to raise event...")
Console.ReadKey(True)
RaiseEvent GlobalEvent(Nothing, EventArgs.Empty)
Console.WriteLine("Press any key to quit...")
Console.ReadKey(True)
End Sub
End Module
End Namespace
现在创建消费者项目。我将我的命名为 GlobalEventConsumer。我删除了默认命名空间并在此处明确声明(如上):
Namespace GlobalEventConsumer
Public Interface IGlobalEventOwner
Event GlobalEvent As EventHandler
End Interface
Public Class Class1
Public Sub New(ByVal globalEvent As IGlobalEventOwner)
AddHandler globalEvent.GlobalEvent, AddressOf GlobalEventHandler
End Sub
Public Shared Sub GlobalEventHandler(ByVal sender As Object, ByVal e As EventArgs)
Console.WriteLine("Event Handled!")
End Sub
End Class
End Namespace
请注意,我已经声明了一个名为“IGlobalEventOwner”的接口。它所做的只是定义一个带有事件的对象。此事件的签名与我们要处理的全局事件相同。
返回示例项目并创建对消费者项目的引用。
消费者项目需要一个实现 IGlobalEventOwner 的对象。模块无法实现接口,因此我们创建了一个私有类 GlobalEventRouter,它将简单地处理模块的事件,然后触发它自己的事件。最后,我们将在 Main sub 中创建一个 Class 1 的新实例,并传递一个 GlobalEventRouter 类的实例。
Namespace GlobalEventSample
Public Module Module1
Public Event GlobalEvent As EventHandler
Public Sub Main()
Dim consumer As New GlobalEventConsumer.Class1(New GlobalEventRouter())
Console.WriteLine("Press any key to raise event...")
Console.ReadKey(True)
RaiseEvent GlobalEvent(Nothing, EventArgs.Empty)
Console.WriteLine("Press any key to quit...")
Console.ReadKey(True)
End Sub
Private Class GlobalEventRouter
Implements GlobalEventConsumer.IGlobalEventOwner
Public Event GlobalEvent(ByVal sender As Object, ByVal e As System.EventArgs) Implements GlobalEventConsumer.IGlobalEventOwner.GlobalEvent
Public Sub New()
AddHandler Module1.GlobalEvent, AddressOf GlobalEventHandler
End Sub
Private Sub GlobalEventHandler(ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent GlobalEvent(sender, e)
End Sub
End Class
End Module
End Namespace
输出:
按任意键引发事件...
事件已处理!
按任意键退出...