Generics to the rescue! Again!

22 May 2009

I was writing a component at work that has many events that all need to be thread safe, and was getting annoyed at the amount of duplicate code I was writing:

Public Event FilterStart(ByVal sender As Object, ByVal e As EventArgs)
'...
Private Delegate Sub OnFilterCompleteDelegate(ByVal sender As Object, ByVal e As FilterCompleteEventArgs)
'...
Private Sub OnFilterComplete(ByVal sender As Object, ByVal e As DataAccess.LoadEventArgs)
    If _parent.InvokeRequired Then
        _parent.Invoke(new OnFilterCompleteDelegate(AddressOf OnFilterComplete), new Object() {sender, e})
    Else
        RaiseEvent FullResultsStart(sender, e)
    End If
End Sub
'... repeat for all

Hmm. There has to be a better way of doing this. Enter some Generic magic in the form of a Generic Delegate Sub:

Private Delegate Sub EventAction(Of TArgs)(ByVal sender As Object, ByVal args As TArgs)

This then allows me to write my Event Raisers like so:

Private Delegate Sub EventAction(Of TArgs)(ByVal sender As Object, ByVal args As TArgs)

Private Sub OnFilterStart(ByVal sender As Object, ByVal e As EventArgs)
    If _parent.InvokeRequired Then
        _parent.Invoke(New EventAction(Of EventArgs)(AddressOf OnFilterStart), New Object() {sender, e})
    Else
        RaiseEvent FilterStart(sender, e)
    End If
End Sub

Further optimisation let me do the fiollowing, as the sender is always Me :

Private Sub OnFilterStart(ByVal e As EventArgs)
    If _parent.InvokeRequired Then
        _parent.Invoke(New Action(Of EventArgs)(AddressOf OnFilterStart), New Object() {e})
    Else
        RaiseEvent FilterStart(Me, e)
    End If
End Sub

Which meant I no longer needed my customer Action Delegate, as there is one for a single parameter in System for this already!

Now if only I could find a way to wrap the thread safe checks and invokes into a single generic function...

design, code, generics, net

« Using Laziness Microcontrollers for MenuItems »
comments powered by Disqus