Вопрос

Is it possible, to raise a global event in a multiproject solution in VB.Net. For example, project 1 has a form called Form1. On Form1 there is a button, that when clicked, raises an event, where project2 can handle that event, and even project3 could handle that event.

Это было полезно?

Решение

You can have a dedicated Project that has a Class whose sole purpose is to house a "Global Event". Make that Class implement the Singleton Pattern so that all the projects will access the same instance. All the other projects can Reference this Project and could look like this:

' 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

Here is FormA in Project1, displaying FormB in Project2 (Project1 has a reference to both Project2 and Project3). We grab the singleton instance and call the RingTheBell() method to raise the "Global Event":

' 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

Finally, over in Project2, we also grab the singleton instance and subscribe to its GlobalEvent (Project2 only has a reference to 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

So any Project that wants to subscribe to the "Global Event" simply adds a Reference to Project3 and uses the Instance() method which returns the singleton instance to which that Project can subscribe to the event with.

Другие советы

This is possible via a number of possible routes. I'd prefer dependency injection in this case.

First, create your global event owner project. I named mine GlobalEventSample. I removed the default namespace and declared it here explicitly to make the code structure more obvious:

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

Now create the consumer project. I named mine GlobalEventConsumer. I removed the default namespace and declared it here explicitly (just as above):

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

Notice that I've declared an interface named "IGlobalEventOwner". All it does is define an object with an event. This event has a signature identical to the global event we want to handle.

Go back to the sample project and create a reference to the consumer project.

The consumer project requires an object which implements IGlobalEventOwner. Modules cannot implement interfaces, so we instead create a private class, GlobalEventRouter, which will simply handle the module's event and then fire its own event. Finally, we will create a new instance of Class 1 in the Main sub and pass an instance of the GlobalEventRouter class.

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

The output:

Press any key to raise event...
Event Handled!
Press any key to quit...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top