События в многопроектном решении VB.Net

Возможно ли поднять глобальное событие в мультипроектном решении в VB.Net. Например, проект 1 имеет форму под названием Form1. В Form1 есть кнопка, которая при нажатии вызывает событие, при котором project2 может обработать это событие, и даже project3 может обработать это событие.

2 ответа

Решение

У вас может быть специальный проект, имеющий класс, единственной целью которого является проведение "Глобального мероприятия". Заставьте этот класс реализовать шаблон Singleton, чтобы все проекты имели доступ к одному и тому же экземпляру. Все остальные проекты могут ссылаться на этот проект и могут выглядеть так:

' 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

Вот Форма A в Project1, отображающая FormB в Project2 (Project1 имеет ссылку как на Project2, так и на Project3). Мы берем экземпляр singleton и вызываем метод 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 мы также получаем экземпляр singleton и подписываемся на его 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, который будет просто обрабатывать событие модуля, а затем запускать его собственное событие. Наконец, мы создадим новый экземпляр класса 1 в подпрограмме Main и передадим экземпляр класса 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

Выход:

Нажмите любую клавишу, чтобы вызвать событие...
Событие обработано!
Нажмите любую клавишу, чтобы выйти...

Другие вопросы по тегам