需要编写一个将AddHandler应用于适当事件的通用方法

时间:2017-07-28 16:18:35

标签: vb.net generics events delegates

我有一个活动中心,我的Winforms应用程序中的不同演示者发布事件,以便在需要时彼此通信。我相信有更好的方法可以做到这一点,但这就是我所拥有的。以下是我的问题的相关部分的片段。一切正常,除了我需要帮助创建一个通用的发布方法。我不想为Cmnd + shift + N创建一堆重载,每个事件一个。我想要一个Sub Publish,它可以理想地采用一种类型(或者你带来的任何东西),执行强制转换,并添加适当的处理程序。

Sub Publish

'' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''” “”“”“”“”“”“”“”“”“”“”“”“”“”” '编辑:添加了一个人为的示例,显示了以下用法:

Public Delegate Sub LoginAttemptedHandler(ByVal sender As Object, ByVal e As LoginAttemptedEventArgs)

Public Class LoginAttemptedEventArgs
    Inherits CustomEventArgs

    Public Property BranchLocation As BranchLocation
    Public Property Username As String

    Public Sub New(ByVal branchLocation As BranchLocation, ByVal username As String)
        Me.BranchLocation = branchLocation
        Me.Username = username
        EventName = "LoginAttempted"
    End Sub
End Class

Public Class CustomEventArgs
    Inherits EventArgs

    Public Property EventName As String
End Class

public Class EventHub
    Private Shared ReadOnly eventTable As New Dictionary(Of String, List(Of [Delegate]))

    Public WriteOnly Property RaiseLoginAttempted As LoginAttemptedEventArgs
        Set(ByVal value As LoginAttemptedEventArgs)
            RaiseEvent LoginAttempted(Me, value)
        End Set
    End Property

   Public Sub Publish(ByVal sender As Object, ByVal e As CustomEventArgs)
        Dim properties As PropertyInfo() = GetType(EventHub).GetProperties
        Dim count = 0
        For Each p As PropertyInfo In properties
            If p.Name.Contains(e.EventName) Then
                p.SetValue(Me, e, Nothing)
                count += 1
            End If
        Next
        'Validate that two events were not called by accident. Each property name should contain
        'the name of exaclty one event, and should correspond to exactly one event.
        If count > 1 Then Throw New Exception("Two or more properties share the same event name")
    End Sub

    Public Sub UnRegister(ByVal handler As LoginAttemptedHandler)
        RemoveHandler LoginAttempted, handler
    End Sub

    Public Sub Register(ByVal handler As LoginAttemptedHandler)
        'AddHandler LoginAttempted, handler
        'Instead of the above line, I need to make this generic to any delegate, not a specific one like LoginAttemptedHandler in this case.
    End Sub

    Public Custom Event LoginAttempted As LoginAttemptedHandler
        AddHandler(ByVal value As LoginAttemptedHandler)
            SyncLock eventTable
                Dim key = "LoginAttempted"
                If Not eventTable.ContainsKey(key) Then eventTable.Add(key, New List(Of [Delegate]))
                eventTable(key).Add(value)
            End SyncLock
        End AddHandler
        RemoveHandler(ByVal value As LoginAttemptedHandler)
            SyncLock eventTable
                eventTable("LoginAttempted").Remove(value)
            End SyncLock
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As LoginAttemptedEventArgs)
            Dim key = e.EventName
            If eventTable.ContainsKey(key) Then
                Dim delegateList = eventTable(key)
                For Each handler As [Delegate] In delegateList
                    Dim fn = DirectCast(handler, LoginAttemptedHandler)
                    fn(sender, e)
                Next
            End If
        End RaiseEvent
    End Event
End Class

0 个答案:

没有答案