|
An ordinary VB developer shares his own successes and failures |
|
| Home News Articles Resources Tips Downloads About me | ||
Advanced reflection - BindEventsByName..NET Reflection used for dynamic event binding.When programming user interfaces in .NET, I've been using events extensively to implement the Observer design pattern.
However, as the number of events grows, the act of
adding and removing event handlers might become
tedious. With a little help of naming convention
and .NET Reflection, one can shrink the numerous
As an example, let's have the following Public Class Block ... Public Event CaptionChanging(...) Public Event CaptionChanged(...) Public Event ColorChanging(...) Public Event ColorChanged(...) Public Event IdChanging(...) Public Event IdChanged(...) ... End ClassThe various Observers can use the WithEvents
keyword, which handles the event registration and
unregistration automatically:
Public Class SomeObserver
Private WithEvents _Block As Block
...
Private Sub _Block_CaptionChanging(...) _
Handles Block.CaptionChanging
...
End Class
However, when you want to handle events for a
local Block reference, you have to use the
Add/RemoveHandler statements
(details here).
When the number
of events is large, writing the Add/RemoveHander
calls can become tedious and error prone.
You can avoid the numerous Dim B As New Block() AddHandler B.ColorChanging, AddressOf Me.OnColorChanging AddHandler B.ColorChanged, AddressOf Me.OnColorChanged AddHandler B.IdChanging, AddressOf Me.OnIdChanging AddHandler B.IdChanged, AddressOf Me.OnIdChangedYou can write this: Dim B As New Block() Utility.BindEventsByName(B, Me, True, "On", String.Empty)Here is the (now famous )
BindEventsByName
method:
Public Class Utility
Public Shared Sub BindEventsByName( _
ByVal sender As Object, _
ByVal receiver As Object, _
ByVal bind As Boolean, _
ByVal handlerPrefix As String, _
ByVal handlerSufix As String)
' Get the sender's (Subject) public events.
Dim SenderEvents() As System.Reflection.EventInfo = sender.GetType().GetEvents()
' Get the receiver's type and lookup its public
' methods matching the naming convention:
' handlerPrefix<EventName>handlerSufix
Dim ReceiverType As Type = receiver.GetType()
Dim E As System.Reflection.EventInfo
Dim Method As System.Reflection.MethodInfo
For Each E In SenderEvents
Method = ReceiverType.GetMethod( _
handlerPrefix & E.Name & handlerSufix, _
System.Reflection.BindingFlags.IgnoreCase Or _
System.Reflection.BindingFlags.Instance Or _
System.Reflection.BindingFlags.NonPublic)
If Not Method Is Nothing Then
Dim D As System.Delegate = System.Delegate.CreateDelegate(E.EventHandlerType, receiver, Method.Name)
If bind Then
E.AddEventHandler(sender, D)
Else
E.RemoveEventHandler(sender, D)
End If
End If
Next
End Sub
End Class
*** Important note ***
The code doesn't check that the event handler
signatures match the event delegates (it would be
much more complex in that case). When the
signatures don't match, the call to Is it worth it?
It depends. As usually, you have to decide for yourself.
|
||
|
|
||
| ©2003-2008 Palo Mraz. All Rights Reserved. See my 'new browser window' policy | ||